36 |
37 | // MinHook Error Codes.
38 | typedef enum MH_STATUS
39 | {
40 | // Unknown error. Should not be returned.
41 | MH_UNKNOWN = -1,
42 |
43 | // Successful.
44 | MH_OK = 0,
45 |
46 | // MinHook is already initialized.
47 | MH_ERROR_ALREADY_INITIALIZED,
48 |
49 | // MinHook is not initialized yet, or already uninitialized.
50 | MH_ERROR_NOT_INITIALIZED,
51 |
52 | // The hook for the specified target function is already created.
53 | MH_ERROR_ALREADY_CREATED,
54 |
55 | // The hook for the specified target function is not created yet.
56 | MH_ERROR_NOT_CREATED,
57 |
58 | // The hook for the specified target function is already enabled.
59 | MH_ERROR_ENABLED,
60 |
61 | // The hook for the specified target function is not enabled yet, or already
62 | // disabled.
63 | MH_ERROR_DISABLED,
64 |
65 | // The specified pointer is invalid. It points the address of non-allocated
66 | // and/or non-executable region.
67 | MH_ERROR_NOT_EXECUTABLE,
68 |
69 | // The specified target function cannot be hooked.
70 | MH_ERROR_UNSUPPORTED_FUNCTION,
71 |
72 | // Failed to allocate memory.
73 | MH_ERROR_MEMORY_ALLOC,
74 |
75 | // Failed to change the memory protection.
76 | MH_ERROR_MEMORY_PROTECT,
77 |
78 | // The specified module is not loaded.
79 | MH_ERROR_MODULE_NOT_FOUND,
80 |
81 | // The specified function is not found.
82 | MH_ERROR_FUNCTION_NOT_FOUND
83 | }
84 | MH_STATUS;
85 |
86 | // Can be passed as a parameter to MH_EnableHook, MH_DisableHook,
87 | // MH_QueueEnableHook or MH_QueueDisableHook.
88 | #define MH_ALL_HOOKS NULL
89 |
90 | #ifdef __cplusplus
91 | extern "C" {
92 | #endif
93 |
94 | // Initialize the MinHook library. You must call this function EXACTLY ONCE
95 | // at the beginning of your program.
96 | MH_STATUS WINAPI MH_Initialize(VOID);
97 |
98 | // Uninitialize the MinHook library. You must call this function EXACTLY
99 | // ONCE at the end of your program.
100 | MH_STATUS WINAPI MH_Uninitialize(VOID);
101 |
102 | // Creates a hook for the specified target function, in disabled state.
103 | // Parameters:
104 | // pTarget [in] A pointer to the target function, which will be
105 | // overridden by the detour function.
106 | // pDetour [in] A pointer to the detour function, which will override
107 | // the target function.
108 | // ppOriginal [out] A pointer to the trampoline function, which will be
109 | // used to call the original target function.
110 | // This parameter can be NULL.
111 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal);
112 |
113 | // Creates a hook for the specified API function, in disabled state.
114 | // Parameters:
115 | // pszModule [in] A pointer to the loaded module name which contains the
116 | // target function.
117 | // pszProcName [in] A pointer to the target function name, which will be
118 | // overridden by the detour function.
119 | // pDetour [in] A pointer to the detour function, which will override
120 | // the target function.
121 | // ppOriginal [out] A pointer to the trampoline function, which will be
122 | // used to call the original target function.
123 | // This parameter can be NULL.
124 | MH_STATUS WINAPI MH_CreateHookApi(
125 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal);
126 |
127 | // Creates a hook for the specified API function, in disabled state.
128 | // Parameters:
129 | // pszModule [in] A pointer to the loaded module name which contains the
130 | // target function.
131 | // pszProcName [in] A pointer to the target function name, which will be
132 | // overridden by the detour function.
133 | // pDetour [in] A pointer to the detour function, which will override
134 | // the target function.
135 | // ppOriginal [out] A pointer to the trampoline function, which will be
136 | // used to call the original target function.
137 | // This parameter can be NULL.
138 | // ppTarget [out] A pointer to the target function, which will be used
139 | // with other functions.
140 | // This parameter can be NULL.
141 | MH_STATUS WINAPI MH_CreateHookApiEx(
142 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget);
143 |
144 | // Removes an already created hook.
145 | // Parameters:
146 | // pTarget [in] A pointer to the target function.
147 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget);
148 |
149 | // Enables an already created hook.
150 | // Parameters:
151 | // pTarget [in] A pointer to the target function.
152 | // If this parameter is MH_ALL_HOOKS, all created hooks are
153 | // enabled in one go.
154 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget);
155 |
156 | // Disables an already created hook.
157 | // Parameters:
158 | // pTarget [in] A pointer to the target function.
159 | // If this parameter is MH_ALL_HOOKS, all created hooks are
160 | // disabled in one go.
161 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget);
162 |
163 | // Queues to enable an already created hook.
164 | // Parameters:
165 | // pTarget [in] A pointer to the target function.
166 | // If this parameter is MH_ALL_HOOKS, all created hooks are
167 | // queued to be enabled.
168 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget);
169 |
170 | // Queues to disable an already created hook.
171 | // Parameters:
172 | // pTarget [in] A pointer to the target function.
173 | // If this parameter is MH_ALL_HOOKS, all created hooks are
174 | // queued to be disabled.
175 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget);
176 |
177 | // Applies all queued changes in one go.
178 | MH_STATUS WINAPI MH_ApplyQueued(VOID);
179 |
180 | // Translates the MH_STATUS to its name as a string.
181 | const char * WINAPI MH_StatusToString(MH_STATUS status);
182 |
183 | #ifdef __cplusplus
184 | }
185 | #endif
186 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | JVM Native Class Dumper
4 |
10 |
11 | Simple native jvm class dumper written in C by hook ClassLoader
12 |
13 | ## What is used for?
14 |
15 | This tool allows you to dump all java classes passed through the ClassLoader. If app decrypt or modify their classes at runtime and there's no easy way to decrypt them or view statically, you can just use this tool and dump decrypted classes from memory.
16 | All classes are dumped into location "C:\\JavaClassDump\\"
17 |
18 |
19 | ## Building
20 |
21 | ### Visual Studio
22 | Simplest way to build project. Just import or clone repo and click "Build". Simple as that.
23 |
24 | ### Command line
25 | Just run `msbuild /m /p:Configuration=Release .`
26 |
27 | ## Screenshots
28 |
29 | 
30 |
31 | ## License
32 |
33 | [MPL-2.0](https://github.com/TheEasyPeasy/Java-Runtime-ClassDumper/blob/master/LICENSE)
34 |
35 | Copyright (c) 2021-present, TheEasyPeasy
36 |
--------------------------------------------------------------------------------
/buffer.c:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #include
30 | #include "buffer.h"
31 |
32 | // Size of each memory block. (= page size of VirtualAlloc)
33 | #define MEMORY_BLOCK_SIZE 0x1000
34 |
35 | // Max range for seeking a memory block. (= 1024MB)
36 | #define MAX_MEMORY_RANGE 0x40000000
37 |
38 | // Memory protection flags to check the executable address.
39 | #define PAGE_EXECUTE_FLAGS \
40 | (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
41 |
42 | // Memory slot.
43 | typedef struct _MEMORY_SLOT
44 | {
45 | union
46 | {
47 | struct _MEMORY_SLOT *pNext;
48 | UINT8 buffer[MEMORY_SLOT_SIZE];
49 | };
50 | } MEMORY_SLOT, *PMEMORY_SLOT;
51 |
52 | // Memory block info. Placed at the head of each block.
53 | typedef struct _MEMORY_BLOCK
54 | {
55 | struct _MEMORY_BLOCK *pNext;
56 | PMEMORY_SLOT pFree; // First element of the free slot list.
57 | UINT usedCount;
58 | } MEMORY_BLOCK, *PMEMORY_BLOCK;
59 |
60 | //-------------------------------------------------------------------------
61 | // Global Variables:
62 | //-------------------------------------------------------------------------
63 |
64 | // First element of the memory block list.
65 | PMEMORY_BLOCK g_pMemoryBlocks;
66 |
67 | //-------------------------------------------------------------------------
68 | VOID InitializeBuffer(VOID)
69 | {
70 | // Nothing to do for now.
71 | }
72 |
73 | //-------------------------------------------------------------------------
74 | VOID UninitializeBuffer(VOID)
75 | {
76 | PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
77 | g_pMemoryBlocks = NULL;
78 |
79 | while (pBlock)
80 | {
81 | PMEMORY_BLOCK pNext = pBlock->pNext;
82 | VirtualFree(pBlock, 0, MEM_RELEASE);
83 | pBlock = pNext;
84 | }
85 | }
86 |
87 | //-------------------------------------------------------------------------
88 | #if defined(_M_X64) || defined(__x86_64__)
89 | static LPVOID FindPrevFreeRegion(LPVOID pAddress, LPVOID pMinAddr, DWORD dwAllocationGranularity)
90 | {
91 | ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
92 |
93 | // Round down to the allocation granularity.
94 | tryAddr -= tryAddr % dwAllocationGranularity;
95 |
96 | // Start from the previous allocation granularity multiply.
97 | tryAddr -= dwAllocationGranularity;
98 |
99 | while (tryAddr >= (ULONG_PTR)pMinAddr)
100 | {
101 | MEMORY_BASIC_INFORMATION mbi;
102 | if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
103 | break;
104 |
105 | if (mbi.State == MEM_FREE)
106 | return (LPVOID)tryAddr;
107 |
108 | if ((ULONG_PTR)mbi.AllocationBase < dwAllocationGranularity)
109 | break;
110 |
111 | tryAddr = (ULONG_PTR)mbi.AllocationBase - dwAllocationGranularity;
112 | }
113 |
114 | return NULL;
115 | }
116 | #endif
117 |
118 | //-------------------------------------------------------------------------
119 | #if defined(_M_X64) || defined(__x86_64__)
120 | static LPVOID FindNextFreeRegion(LPVOID pAddress, LPVOID pMaxAddr, DWORD dwAllocationGranularity)
121 | {
122 | ULONG_PTR tryAddr = (ULONG_PTR)pAddress;
123 |
124 | // Round down to the allocation granularity.
125 | tryAddr -= tryAddr % dwAllocationGranularity;
126 |
127 | // Start from the next allocation granularity multiply.
128 | tryAddr += dwAllocationGranularity;
129 |
130 | while (tryAddr <= (ULONG_PTR)pMaxAddr)
131 | {
132 | MEMORY_BASIC_INFORMATION mbi;
133 | if (VirtualQuery((LPVOID)tryAddr, &mbi, sizeof(mbi)) == 0)
134 | break;
135 |
136 | if (mbi.State == MEM_FREE)
137 | return (LPVOID)tryAddr;
138 |
139 | tryAddr = (ULONG_PTR)mbi.BaseAddress + mbi.RegionSize;
140 |
141 | // Round up to the next allocation granularity.
142 | tryAddr += dwAllocationGranularity - 1;
143 | tryAddr -= tryAddr % dwAllocationGranularity;
144 | }
145 |
146 | return NULL;
147 | }
148 | #endif
149 |
150 | //-------------------------------------------------------------------------
151 | static PMEMORY_BLOCK GetMemoryBlock(LPVOID pOrigin)
152 | {
153 | PMEMORY_BLOCK pBlock;
154 | #if defined(_M_X64) || defined(__x86_64__)
155 | ULONG_PTR minAddr;
156 | ULONG_PTR maxAddr;
157 |
158 | SYSTEM_INFO si;
159 | GetSystemInfo(&si);
160 | minAddr = (ULONG_PTR)si.lpMinimumApplicationAddress;
161 | maxAddr = (ULONG_PTR)si.lpMaximumApplicationAddress;
162 |
163 | // pOrigin ± 512MB
164 | if ((ULONG_PTR)pOrigin > MAX_MEMORY_RANGE && minAddr < (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE)
165 | minAddr = (ULONG_PTR)pOrigin - MAX_MEMORY_RANGE;
166 |
167 | if (maxAddr > (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE)
168 | maxAddr = (ULONG_PTR)pOrigin + MAX_MEMORY_RANGE;
169 |
170 | // Make room for MEMORY_BLOCK_SIZE bytes.
171 | maxAddr -= MEMORY_BLOCK_SIZE - 1;
172 | #endif
173 |
174 | // Look the registered blocks for a reachable one.
175 | for (pBlock = g_pMemoryBlocks; pBlock != NULL; pBlock = pBlock->pNext)
176 | {
177 | #if defined(_M_X64) || defined(__x86_64__)
178 | // Ignore the blocks too far.
179 | if ((ULONG_PTR)pBlock < minAddr || (ULONG_PTR)pBlock >= maxAddr)
180 | continue;
181 | #endif
182 | // The block has at least one unused slot.
183 | if (pBlock->pFree != NULL)
184 | return pBlock;
185 | }
186 |
187 | #if defined(_M_X64) || defined(__x86_64__)
188 | // Alloc a new block above if not found.
189 | {
190 | LPVOID pAlloc = pOrigin;
191 | while ((ULONG_PTR)pAlloc >= minAddr)
192 | {
193 | pAlloc = FindPrevFreeRegion(pAlloc, (LPVOID)minAddr, si.dwAllocationGranularity);
194 | if (pAlloc == NULL)
195 | break;
196 |
197 | pBlock = (PMEMORY_BLOCK)VirtualAlloc(
198 | pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
199 | if (pBlock != NULL)
200 | break;
201 | }
202 | }
203 |
204 | // Alloc a new block below if not found.
205 | if (pBlock == NULL)
206 | {
207 | LPVOID pAlloc = pOrigin;
208 | while ((ULONG_PTR)pAlloc <= maxAddr)
209 | {
210 | pAlloc = FindNextFreeRegion(pAlloc, (LPVOID)maxAddr, si.dwAllocationGranularity);
211 | if (pAlloc == NULL)
212 | break;
213 |
214 | pBlock = (PMEMORY_BLOCK)VirtualAlloc(
215 | pAlloc, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
216 | if (pBlock != NULL)
217 | break;
218 | }
219 | }
220 | #else
221 | // In x86 mode, a memory block can be placed anywhere.
222 | pBlock = (PMEMORY_BLOCK)VirtualAlloc(
223 | NULL, MEMORY_BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
224 | #endif
225 |
226 | if (pBlock != NULL)
227 | {
228 | // Build a linked list of all the slots.
229 | PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBlock + 1;
230 | pBlock->pFree = NULL;
231 | pBlock->usedCount = 0;
232 | do
233 | {
234 | pSlot->pNext = pBlock->pFree;
235 | pBlock->pFree = pSlot;
236 | pSlot++;
237 | } while ((ULONG_PTR)pSlot - (ULONG_PTR)pBlock <= MEMORY_BLOCK_SIZE - MEMORY_SLOT_SIZE);
238 |
239 | pBlock->pNext = g_pMemoryBlocks;
240 | g_pMemoryBlocks = pBlock;
241 | }
242 |
243 | return pBlock;
244 | }
245 |
246 | //-------------------------------------------------------------------------
247 | LPVOID AllocateBuffer(LPVOID pOrigin)
248 | {
249 | PMEMORY_SLOT pSlot;
250 | PMEMORY_BLOCK pBlock = GetMemoryBlock(pOrigin);
251 | if (pBlock == NULL)
252 | return NULL;
253 |
254 | // Remove an unused slot from the list.
255 | pSlot = pBlock->pFree;
256 | pBlock->pFree = pSlot->pNext;
257 | pBlock->usedCount++;
258 | #ifdef _DEBUG
259 | // Fill the slot with INT3 for debugging.
260 | memset(pSlot, 0xCC, sizeof(MEMORY_SLOT));
261 | #endif
262 | return pSlot;
263 | }
264 |
265 | //-------------------------------------------------------------------------
266 | VOID FreeBuffer(LPVOID pBuffer)
267 | {
268 | PMEMORY_BLOCK pBlock = g_pMemoryBlocks;
269 | PMEMORY_BLOCK pPrev = NULL;
270 | ULONG_PTR pTargetBlock = ((ULONG_PTR)pBuffer / MEMORY_BLOCK_SIZE) * MEMORY_BLOCK_SIZE;
271 |
272 | while (pBlock != NULL)
273 | {
274 | if ((ULONG_PTR)pBlock == pTargetBlock)
275 | {
276 | PMEMORY_SLOT pSlot = (PMEMORY_SLOT)pBuffer;
277 | #ifdef _DEBUG
278 | // Clear the released slot for debugging.
279 | memset(pSlot, 0x00, sizeof(MEMORY_SLOT));
280 | #endif
281 | // Restore the released slot to the list.
282 | pSlot->pNext = pBlock->pFree;
283 | pBlock->pFree = pSlot;
284 | pBlock->usedCount--;
285 |
286 | // Free if unused.
287 | if (pBlock->usedCount == 0)
288 | {
289 | if (pPrev)
290 | pPrev->pNext = pBlock->pNext;
291 | else
292 | g_pMemoryBlocks = pBlock->pNext;
293 |
294 | VirtualFree(pBlock, 0, MEM_RELEASE);
295 | }
296 |
297 | break;
298 | }
299 |
300 | pPrev = pBlock;
301 | pBlock = pBlock->pNext;
302 | }
303 | }
304 |
305 | //-------------------------------------------------------------------------
306 | BOOL IsExecutableAddress(LPVOID pAddress)
307 | {
308 | MEMORY_BASIC_INFORMATION mi;
309 | VirtualQuery(pAddress, &mi, sizeof(mi));
310 |
311 | return (mi.State == MEM_COMMIT && (mi.Protect & PAGE_EXECUTE_FLAGS));
312 | }
313 |
--------------------------------------------------------------------------------
/buffer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 | #include
31 |
32 | // Size of each memory slot.
33 | #if defined(_M_X64) || defined(__x86_64__)
34 | #define MEMORY_SLOT_SIZE 64
35 | #else
36 | #define MEMORY_SLOT_SIZE 32
37 | #endif
38 |
39 | VOID InitializeBuffer(VOID);
40 | VOID UninitializeBuffer(VOID);
41 | LPVOID AllocateBuffer(LPVOID pOrigin);
42 | VOID FreeBuffer(LPVOID pBuffer);
43 | BOOL IsExecutableAddress(LPVOID pAddress);
44 |
--------------------------------------------------------------------------------
/dllmain.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "jvm_dumper.h"
3 |
4 | BOOL APIENTRY DllMain( HMODULE hModule,
5 | DWORD ul_reason_for_call,
6 | LPVOID lpReserved
7 | )
8 | {
9 | switch (ul_reason_for_call)
10 | {
11 | case DLL_PROCESS_ATTACH:
12 | case DLL_THREAD_ATTACH:
13 | case DLL_THREAD_DETACH:
14 | case DLL_PROCESS_DETACH:
15 | CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)hookSetup, NULL, 0, NULL);
16 | break;
17 | }
18 | return TRUE;
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/framework.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define WIN32_LEAN_AND_MEAN // Wyklucz rzadko używane rzeczy z nagłówków systemu Windows
4 | // Pliki nagłówkowe systemu Windows
5 | #include
6 |
--------------------------------------------------------------------------------
/hde32.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 32 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #if defined(_M_IX86) || defined(__i386__)
9 |
10 | #include
11 | #include "hde32.h"
12 | #include "table32.h"
13 |
14 | unsigned int hde32_disasm(const void *code, hde32s *hs)
15 | {
16 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
17 | uint8_t *ht = hde32_table, m_mod, m_reg, m_rm, disp_size = 0;
18 |
19 | memset(hs, 0, sizeof(hde32s));
20 |
21 | for (x = 16; x; x--)
22 | switch (c = *p++) {
23 | case 0xf3:
24 | hs->p_rep = c;
25 | pref |= PRE_F3;
26 | break;
27 | case 0xf2:
28 | hs->p_rep = c;
29 | pref |= PRE_F2;
30 | break;
31 | case 0xf0:
32 | hs->p_lock = c;
33 | pref |= PRE_LOCK;
34 | break;
35 | case 0x26: case 0x2e: case 0x36:
36 | case 0x3e: case 0x64: case 0x65:
37 | hs->p_seg = c;
38 | pref |= PRE_SEG;
39 | break;
40 | case 0x66:
41 | hs->p_66 = c;
42 | pref |= PRE_66;
43 | break;
44 | case 0x67:
45 | hs->p_67 = c;
46 | pref |= PRE_67;
47 | break;
48 | default:
49 | goto pref_done;
50 | }
51 | pref_done:
52 |
53 | hs->flags = (uint32_t)pref << 23;
54 |
55 | if (!pref)
56 | pref |= PRE_NONE;
57 |
58 | if ((hs->opcode = c) == 0x0f) {
59 | hs->opcode2 = c = *p++;
60 | ht += DELTA_OPCODES;
61 | } else if (c >= 0xa0 && c <= 0xa3) {
62 | if (pref & PRE_67)
63 | pref |= PRE_66;
64 | else
65 | pref &= ~PRE_66;
66 | }
67 |
68 | opcode = c;
69 | cflags = ht[ht[opcode / 4] + (opcode % 4)];
70 |
71 | if (cflags == C_ERROR) {
72 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
73 | cflags = 0;
74 | if ((opcode & -3) == 0x24)
75 | cflags++;
76 | }
77 |
78 | x = 0;
79 | if (cflags & C_GROUP) {
80 | uint16_t t;
81 | t = *(uint16_t *)(ht + (cflags & 0x7f));
82 | cflags = (uint8_t)t;
83 | x = (uint8_t)(t >> 8);
84 | }
85 |
86 | if (hs->opcode2) {
87 | ht = hde32_table + DELTA_PREFIXES;
88 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
89 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
90 | }
91 |
92 | if (cflags & C_MODRM) {
93 | hs->flags |= F_MODRM;
94 | hs->modrm = c = *p++;
95 | hs->modrm_mod = m_mod = c >> 6;
96 | hs->modrm_rm = m_rm = c & 7;
97 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
98 |
99 | if (x && ((x << m_reg) & 0x80))
100 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
101 |
102 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
103 | uint8_t t = opcode - 0xd9;
104 | if (m_mod == 3) {
105 | ht = hde32_table + DELTA_FPU_MODRM + t*8;
106 | t = ht[m_reg] << m_rm;
107 | } else {
108 | ht = hde32_table + DELTA_FPU_REG;
109 | t = ht[t] << m_reg;
110 | }
111 | if (t & 0x80)
112 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
113 | }
114 |
115 | if (pref & PRE_LOCK) {
116 | if (m_mod == 3) {
117 | hs->flags |= F_ERROR | F_ERROR_LOCK;
118 | } else {
119 | uint8_t *table_end, op = opcode;
120 | if (hs->opcode2) {
121 | ht = hde32_table + DELTA_OP2_LOCK_OK;
122 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
123 | } else {
124 | ht = hde32_table + DELTA_OP_LOCK_OK;
125 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
126 | op &= -2;
127 | }
128 | for (; ht != table_end; ht++)
129 | if (*ht++ == op) {
130 | if (!((*ht << m_reg) & 0x80))
131 | goto no_lock_error;
132 | else
133 | break;
134 | }
135 | hs->flags |= F_ERROR | F_ERROR_LOCK;
136 | no_lock_error:
137 | ;
138 | }
139 | }
140 |
141 | if (hs->opcode2) {
142 | switch (opcode) {
143 | case 0x20: case 0x22:
144 | m_mod = 3;
145 | if (m_reg > 4 || m_reg == 1)
146 | goto error_operand;
147 | else
148 | goto no_error_operand;
149 | case 0x21: case 0x23:
150 | m_mod = 3;
151 | if (m_reg == 4 || m_reg == 5)
152 | goto error_operand;
153 | else
154 | goto no_error_operand;
155 | }
156 | } else {
157 | switch (opcode) {
158 | case 0x8c:
159 | if (m_reg > 5)
160 | goto error_operand;
161 | else
162 | goto no_error_operand;
163 | case 0x8e:
164 | if (m_reg == 1 || m_reg > 5)
165 | goto error_operand;
166 | else
167 | goto no_error_operand;
168 | }
169 | }
170 |
171 | if (m_mod == 3) {
172 | uint8_t *table_end;
173 | if (hs->opcode2) {
174 | ht = hde32_table + DELTA_OP2_ONLY_MEM;
175 | table_end = ht + sizeof(hde32_table) - DELTA_OP2_ONLY_MEM;
176 | } else {
177 | ht = hde32_table + DELTA_OP_ONLY_MEM;
178 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
179 | }
180 | for (; ht != table_end; ht += 2)
181 | if (*ht++ == opcode) {
182 | if ((*ht++ & pref) && !((*ht << m_reg) & 0x80))
183 | goto error_operand;
184 | else
185 | break;
186 | }
187 | goto no_error_operand;
188 | } else if (hs->opcode2) {
189 | switch (opcode) {
190 | case 0x50: case 0xd7: case 0xf7:
191 | if (pref & (PRE_NONE | PRE_66))
192 | goto error_operand;
193 | break;
194 | case 0xd6:
195 | if (pref & (PRE_F2 | PRE_F3))
196 | goto error_operand;
197 | break;
198 | case 0xc5:
199 | goto error_operand;
200 | }
201 | goto no_error_operand;
202 | } else
203 | goto no_error_operand;
204 |
205 | error_operand:
206 | hs->flags |= F_ERROR | F_ERROR_OPERAND;
207 | no_error_operand:
208 |
209 | c = *p++;
210 | if (m_reg <= 1) {
211 | if (opcode == 0xf6)
212 | cflags |= C_IMM8;
213 | else if (opcode == 0xf7)
214 | cflags |= C_IMM_P66;
215 | }
216 |
217 | switch (m_mod) {
218 | case 0:
219 | if (pref & PRE_67) {
220 | if (m_rm == 6)
221 | disp_size = 2;
222 | } else
223 | if (m_rm == 5)
224 | disp_size = 4;
225 | break;
226 | case 1:
227 | disp_size = 1;
228 | break;
229 | case 2:
230 | disp_size = 2;
231 | if (!(pref & PRE_67))
232 | disp_size <<= 1;
233 | break;
234 | }
235 |
236 | if (m_mod != 3 && m_rm == 4 && !(pref & PRE_67)) {
237 | hs->flags |= F_SIB;
238 | p++;
239 | hs->sib = c;
240 | hs->sib_scale = c >> 6;
241 | hs->sib_index = (c & 0x3f) >> 3;
242 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
243 | disp_size = 4;
244 | }
245 |
246 | p--;
247 | switch (disp_size) {
248 | case 1:
249 | hs->flags |= F_DISP8;
250 | hs->disp.disp8 = *p;
251 | break;
252 | case 2:
253 | hs->flags |= F_DISP16;
254 | hs->disp.disp16 = *(uint16_t *)p;
255 | break;
256 | case 4:
257 | hs->flags |= F_DISP32;
258 | hs->disp.disp32 = *(uint32_t *)p;
259 | break;
260 | }
261 | p += disp_size;
262 | } else if (pref & PRE_LOCK)
263 | hs->flags |= F_ERROR | F_ERROR_LOCK;
264 |
265 | if (cflags & C_IMM_P66) {
266 | if (cflags & C_REL32) {
267 | if (pref & PRE_66) {
268 | hs->flags |= F_IMM16 | F_RELATIVE;
269 | hs->imm.imm16 = *(uint16_t *)p;
270 | p += 2;
271 | goto disasm_done;
272 | }
273 | goto rel32_ok;
274 | }
275 | if (pref & PRE_66) {
276 | hs->flags |= F_IMM16;
277 | hs->imm.imm16 = *(uint16_t *)p;
278 | p += 2;
279 | } else {
280 | hs->flags |= F_IMM32;
281 | hs->imm.imm32 = *(uint32_t *)p;
282 | p += 4;
283 | }
284 | }
285 |
286 | if (cflags & C_IMM16) {
287 | if (hs->flags & F_IMM32) {
288 | hs->flags |= F_IMM16;
289 | hs->disp.disp16 = *(uint16_t *)p;
290 | } else if (hs->flags & F_IMM16) {
291 | hs->flags |= F_2IMM16;
292 | hs->disp.disp16 = *(uint16_t *)p;
293 | } else {
294 | hs->flags |= F_IMM16;
295 | hs->imm.imm16 = *(uint16_t *)p;
296 | }
297 | p += 2;
298 | }
299 | if (cflags & C_IMM8) {
300 | hs->flags |= F_IMM8;
301 | hs->imm.imm8 = *p++;
302 | }
303 |
304 | if (cflags & C_REL32) {
305 | rel32_ok:
306 | hs->flags |= F_IMM32 | F_RELATIVE;
307 | hs->imm.imm32 = *(uint32_t *)p;
308 | p += 4;
309 | } else if (cflags & C_REL8) {
310 | hs->flags |= F_IMM8 | F_RELATIVE;
311 | hs->imm.imm8 = *p++;
312 | }
313 |
314 | disasm_done:
315 |
316 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
317 | hs->flags |= F_ERROR | F_ERROR_LENGTH;
318 | hs->len = 15;
319 | }
320 |
321 | return (unsigned int)hs->len;
322 | }
323 |
324 | #endif // defined(_M_IX86) || defined(__i386__)
325 |
--------------------------------------------------------------------------------
/hde32.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 32
3 | * Copyright (c) 2006-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | * hde32.h: C/C++ header file
7 | *
8 | */
9 |
10 | #ifndef _HDE32_H_
11 | #define _HDE32_H_
12 |
13 | /* stdint.h - C99 standard header
14 | * http://en.wikipedia.org/wiki/stdint.h
15 | *
16 | * if your compiler doesn't contain "stdint.h" header (for
17 | * example, Microsoft Visual C++), you can download file:
18 | * http://www.azillionmonkeys.com/qed/pstdint.h
19 | * and change next line to:
20 | * #include "pstdint.h"
21 | */
22 | #include "pstdint.h"
23 |
24 | #define F_MODRM 0x00000001
25 | #define F_SIB 0x00000002
26 | #define F_IMM8 0x00000004
27 | #define F_IMM16 0x00000008
28 | #define F_IMM32 0x00000010
29 | #define F_DISP8 0x00000020
30 | #define F_DISP16 0x00000040
31 | #define F_DISP32 0x00000080
32 | #define F_RELATIVE 0x00000100
33 | #define F_2IMM16 0x00000800
34 | #define F_ERROR 0x00001000
35 | #define F_ERROR_OPCODE 0x00002000
36 | #define F_ERROR_LENGTH 0x00004000
37 | #define F_ERROR_LOCK 0x00008000
38 | #define F_ERROR_OPERAND 0x00010000
39 | #define F_PREFIX_REPNZ 0x01000000
40 | #define F_PREFIX_REPX 0x02000000
41 | #define F_PREFIX_REP 0x03000000
42 | #define F_PREFIX_66 0x04000000
43 | #define F_PREFIX_67 0x08000000
44 | #define F_PREFIX_LOCK 0x10000000
45 | #define F_PREFIX_SEG 0x20000000
46 | #define F_PREFIX_ANY 0x3f000000
47 |
48 | #define PREFIX_SEGMENT_CS 0x2e
49 | #define PREFIX_SEGMENT_SS 0x36
50 | #define PREFIX_SEGMENT_DS 0x3e
51 | #define PREFIX_SEGMENT_ES 0x26
52 | #define PREFIX_SEGMENT_FS 0x64
53 | #define PREFIX_SEGMENT_GS 0x65
54 | #define PREFIX_LOCK 0xf0
55 | #define PREFIX_REPNZ 0xf2
56 | #define PREFIX_REPX 0xf3
57 | #define PREFIX_OPERAND_SIZE 0x66
58 | #define PREFIX_ADDRESS_SIZE 0x67
59 |
60 | #pragma pack(push,1)
61 |
62 | typedef struct {
63 | uint8_t len;
64 | uint8_t p_rep;
65 | uint8_t p_lock;
66 | uint8_t p_seg;
67 | uint8_t p_66;
68 | uint8_t p_67;
69 | uint8_t opcode;
70 | uint8_t opcode2;
71 | uint8_t modrm;
72 | uint8_t modrm_mod;
73 | uint8_t modrm_reg;
74 | uint8_t modrm_rm;
75 | uint8_t sib;
76 | uint8_t sib_scale;
77 | uint8_t sib_index;
78 | uint8_t sib_base;
79 | union {
80 | uint8_t imm8;
81 | uint16_t imm16;
82 | uint32_t imm32;
83 | } imm;
84 | union {
85 | uint8_t disp8;
86 | uint16_t disp16;
87 | uint32_t disp32;
88 | } disp;
89 | uint32_t flags;
90 | } hde32s;
91 |
92 | #pragma pack(pop)
93 |
94 | #ifdef __cplusplus
95 | extern "C" {
96 | #endif
97 |
98 | /* __cdecl */
99 | unsigned int hde32_disasm(const void *code, hde32s *hs);
100 |
101 | #ifdef __cplusplus
102 | }
103 | #endif
104 |
105 | #endif /* _HDE32_H_ */
106 |
--------------------------------------------------------------------------------
/hde64.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 64 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #if defined(_M_X64) || defined(__x86_64__)
9 |
10 | #include
11 | #include "hde64.h"
12 | #include "table64.h"
13 |
14 | unsigned int hde64_disasm(const void *code, hde64s *hs)
15 | {
16 | uint8_t x, c, *p = (uint8_t *)code, cflags, opcode, pref = 0;
17 | uint8_t *ht = hde64_table, m_mod, m_reg, m_rm, disp_size = 0;
18 | uint8_t op64 = 0;
19 |
20 | memset(hs, 0, sizeof(hde64s));
21 |
22 | for (x = 16; x; x--)
23 | switch (c = *p++) {
24 | case 0xf3:
25 | hs->p_rep = c;
26 | pref |= PRE_F3;
27 | break;
28 | case 0xf2:
29 | hs->p_rep = c;
30 | pref |= PRE_F2;
31 | break;
32 | case 0xf0:
33 | hs->p_lock = c;
34 | pref |= PRE_LOCK;
35 | break;
36 | case 0x26: case 0x2e: case 0x36:
37 | case 0x3e: case 0x64: case 0x65:
38 | hs->p_seg = c;
39 | pref |= PRE_SEG;
40 | break;
41 | case 0x66:
42 | hs->p_66 = c;
43 | pref |= PRE_66;
44 | break;
45 | case 0x67:
46 | hs->p_67 = c;
47 | pref |= PRE_67;
48 | break;
49 | default:
50 | goto pref_done;
51 | }
52 | pref_done:
53 |
54 | hs->flags = (uint32_t)pref << 23;
55 |
56 | if (!pref)
57 | pref |= PRE_NONE;
58 |
59 | if ((c & 0xf0) == 0x40) {
60 | hs->flags |= F_PREFIX_REX;
61 | if ((hs->rex_w = (c & 0xf) >> 3) && (*p & 0xf8) == 0xb8)
62 | op64++;
63 | hs->rex_r = (c & 7) >> 2;
64 | hs->rex_x = (c & 3) >> 1;
65 | hs->rex_b = c & 1;
66 | if (((c = *p++) & 0xf0) == 0x40) {
67 | opcode = c;
68 | goto error_opcode;
69 | }
70 | }
71 |
72 | if ((hs->opcode = c) == 0x0f) {
73 | hs->opcode2 = c = *p++;
74 | ht += DELTA_OPCODES;
75 | } else if (c >= 0xa0 && c <= 0xa3) {
76 | op64++;
77 | if (pref & PRE_67)
78 | pref |= PRE_66;
79 | else
80 | pref &= ~PRE_66;
81 | }
82 |
83 | opcode = c;
84 | cflags = ht[ht[opcode / 4] + (opcode % 4)];
85 |
86 | if (cflags == C_ERROR) {
87 | error_opcode:
88 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
89 | cflags = 0;
90 | if ((opcode & -3) == 0x24)
91 | cflags++;
92 | }
93 |
94 | x = 0;
95 | if (cflags & C_GROUP) {
96 | uint16_t t;
97 | t = *(uint16_t *)(ht + (cflags & 0x7f));
98 | cflags = (uint8_t)t;
99 | x = (uint8_t)(t >> 8);
100 | }
101 |
102 | if (hs->opcode2) {
103 | ht = hde64_table + DELTA_PREFIXES;
104 | if (ht[ht[opcode / 4] + (opcode % 4)] & pref)
105 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
106 | }
107 |
108 | if (cflags & C_MODRM) {
109 | hs->flags |= F_MODRM;
110 | hs->modrm = c = *p++;
111 | hs->modrm_mod = m_mod = c >> 6;
112 | hs->modrm_rm = m_rm = c & 7;
113 | hs->modrm_reg = m_reg = (c & 0x3f) >> 3;
114 |
115 | if (x && ((x << m_reg) & 0x80))
116 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
117 |
118 | if (!hs->opcode2 && opcode >= 0xd9 && opcode <= 0xdf) {
119 | uint8_t t = opcode - 0xd9;
120 | if (m_mod == 3) {
121 | ht = hde64_table + DELTA_FPU_MODRM + t*8;
122 | t = ht[m_reg] << m_rm;
123 | } else {
124 | ht = hde64_table + DELTA_FPU_REG;
125 | t = ht[t] << m_reg;
126 | }
127 | if (t & 0x80)
128 | hs->flags |= F_ERROR | F_ERROR_OPCODE;
129 | }
130 |
131 | if (pref & PRE_LOCK) {
132 | if (m_mod == 3) {
133 | hs->flags |= F_ERROR | F_ERROR_LOCK;
134 | } else {
135 | uint8_t *table_end, op = opcode;
136 | if (hs->opcode2) {
137 | ht = hde64_table + DELTA_OP2_LOCK_OK;
138 | table_end = ht + DELTA_OP_ONLY_MEM - DELTA_OP2_LOCK_OK;
139 | } else {
140 | ht = hde64_table + DELTA_OP_LOCK_OK;
141 | table_end = ht + DELTA_OP2_LOCK_OK - DELTA_OP_LOCK_OK;
142 | op &= -2;
143 | }
144 | for (; ht != table_end; ht++)
145 | if (*ht++ == op) {
146 | if (!((*ht << m_reg) & 0x80))
147 | goto no_lock_error;
148 | else
149 | break;
150 | }
151 | hs->flags |= F_ERROR | F_ERROR_LOCK;
152 | no_lock_error:
153 | ;
154 | }
155 | }
156 |
157 | if (hs->opcode2) {
158 | switch (opcode) {
159 | case 0x20: case 0x22:
160 | m_mod = 3;
161 | if (m_reg > 4 || m_reg == 1)
162 | goto error_operand;
163 | else
164 | goto no_error_operand;
165 | case 0x21: case 0x23:
166 | m_mod = 3;
167 | if (m_reg == 4 || m_reg == 5)
168 | goto error_operand;
169 | else
170 | goto no_error_operand;
171 | }
172 | } else {
173 | switch (opcode) {
174 | case 0x8c:
175 | if (m_reg > 5)
176 | goto error_operand;
177 | else
178 | goto no_error_operand;
179 | case 0x8e:
180 | if (m_reg == 1 || m_reg > 5)
181 | goto error_operand;
182 | else
183 | goto no_error_operand;
184 | }
185 | }
186 |
187 | if (m_mod == 3) {
188 | uint8_t *table_end;
189 | if (hs->opcode2) {
190 | ht = hde64_table + DELTA_OP2_ONLY_MEM;
191 | table_end = ht + sizeof(hde64_table) - DELTA_OP2_ONLY_MEM;
192 | } else {
193 | ht = hde64_table + DELTA_OP_ONLY_MEM;
194 | table_end = ht + DELTA_OP2_ONLY_MEM - DELTA_OP_ONLY_MEM;
195 | }
196 | for (; ht != table_end; ht += 2)
197 | if (*ht++ == opcode) {
198 | if (*ht++ & pref && !((*ht << m_reg) & 0x80))
199 | goto error_operand;
200 | else
201 | break;
202 | }
203 | goto no_error_operand;
204 | } else if (hs->opcode2) {
205 | switch (opcode) {
206 | case 0x50: case 0xd7: case 0xf7:
207 | if (pref & (PRE_NONE | PRE_66))
208 | goto error_operand;
209 | break;
210 | case 0xd6:
211 | if (pref & (PRE_F2 | PRE_F3))
212 | goto error_operand;
213 | break;
214 | case 0xc5:
215 | goto error_operand;
216 | }
217 | goto no_error_operand;
218 | } else
219 | goto no_error_operand;
220 |
221 | error_operand:
222 | hs->flags |= F_ERROR | F_ERROR_OPERAND;
223 | no_error_operand:
224 |
225 | c = *p++;
226 | if (m_reg <= 1) {
227 | if (opcode == 0xf6)
228 | cflags |= C_IMM8;
229 | else if (opcode == 0xf7)
230 | cflags |= C_IMM_P66;
231 | }
232 |
233 | switch (m_mod) {
234 | case 0:
235 | if (pref & PRE_67) {
236 | if (m_rm == 6)
237 | disp_size = 2;
238 | } else
239 | if (m_rm == 5)
240 | disp_size = 4;
241 | break;
242 | case 1:
243 | disp_size = 1;
244 | break;
245 | case 2:
246 | disp_size = 2;
247 | if (!(pref & PRE_67))
248 | disp_size <<= 1;
249 | }
250 |
251 | if (m_mod != 3 && m_rm == 4) {
252 | hs->flags |= F_SIB;
253 | p++;
254 | hs->sib = c;
255 | hs->sib_scale = c >> 6;
256 | hs->sib_index = (c & 0x3f) >> 3;
257 | if ((hs->sib_base = c & 7) == 5 && !(m_mod & 1))
258 | disp_size = 4;
259 | }
260 |
261 | p--;
262 | switch (disp_size) {
263 | case 1:
264 | hs->flags |= F_DISP8;
265 | hs->disp.disp8 = *p;
266 | break;
267 | case 2:
268 | hs->flags |= F_DISP16;
269 | hs->disp.disp16 = *(uint16_t *)p;
270 | break;
271 | case 4:
272 | hs->flags |= F_DISP32;
273 | hs->disp.disp32 = *(uint32_t *)p;
274 | }
275 | p += disp_size;
276 | } else if (pref & PRE_LOCK)
277 | hs->flags |= F_ERROR | F_ERROR_LOCK;
278 |
279 | if (cflags & C_IMM_P66) {
280 | if (cflags & C_REL32) {
281 | if (pref & PRE_66) {
282 | hs->flags |= F_IMM16 | F_RELATIVE;
283 | hs->imm.imm16 = *(uint16_t *)p;
284 | p += 2;
285 | goto disasm_done;
286 | }
287 | goto rel32_ok;
288 | }
289 | if (op64) {
290 | hs->flags |= F_IMM64;
291 | hs->imm.imm64 = *(uint64_t *)p;
292 | p += 8;
293 | } else if (!(pref & PRE_66)) {
294 | hs->flags |= F_IMM32;
295 | hs->imm.imm32 = *(uint32_t *)p;
296 | p += 4;
297 | } else
298 | goto imm16_ok;
299 | }
300 |
301 |
302 | if (cflags & C_IMM16) {
303 | imm16_ok:
304 | hs->flags |= F_IMM16;
305 | hs->imm.imm16 = *(uint16_t *)p;
306 | p += 2;
307 | }
308 | if (cflags & C_IMM8) {
309 | hs->flags |= F_IMM8;
310 | hs->imm.imm8 = *p++;
311 | }
312 |
313 | if (cflags & C_REL32) {
314 | rel32_ok:
315 | hs->flags |= F_IMM32 | F_RELATIVE;
316 | hs->imm.imm32 = *(uint32_t *)p;
317 | p += 4;
318 | } else if (cflags & C_REL8) {
319 | hs->flags |= F_IMM8 | F_RELATIVE;
320 | hs->imm.imm8 = *p++;
321 | }
322 |
323 | disasm_done:
324 |
325 | if ((hs->len = (uint8_t)(p-(uint8_t *)code)) > 15) {
326 | hs->flags |= F_ERROR | F_ERROR_LENGTH;
327 | hs->len = 15;
328 | }
329 |
330 | return (unsigned int)hs->len;
331 | }
332 |
333 | #endif // defined(_M_X64) || defined(__x86_64__)
334 |
--------------------------------------------------------------------------------
/hde64.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 64
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | * hde64.h: C/C++ header file
7 | *
8 | */
9 |
10 | #ifndef _HDE64_H_
11 | #define _HDE64_H_
12 |
13 | /* stdint.h - C99 standard header
14 | * http://en.wikipedia.org/wiki/stdint.h
15 | *
16 | * if your compiler doesn't contain "stdint.h" header (for
17 | * example, Microsoft Visual C++), you can download file:
18 | * http://www.azillionmonkeys.com/qed/pstdint.h
19 | * and change next line to:
20 | * #include "pstdint.h"
21 | */
22 | #include "pstdint.h"
23 |
24 | #define F_MODRM 0x00000001
25 | #define F_SIB 0x00000002
26 | #define F_IMM8 0x00000004
27 | #define F_IMM16 0x00000008
28 | #define F_IMM32 0x00000010
29 | #define F_IMM64 0x00000020
30 | #define F_DISP8 0x00000040
31 | #define F_DISP16 0x00000080
32 | #define F_DISP32 0x00000100
33 | #define F_RELATIVE 0x00000200
34 | #define F_ERROR 0x00001000
35 | #define F_ERROR_OPCODE 0x00002000
36 | #define F_ERROR_LENGTH 0x00004000
37 | #define F_ERROR_LOCK 0x00008000
38 | #define F_ERROR_OPERAND 0x00010000
39 | #define F_PREFIX_REPNZ 0x01000000
40 | #define F_PREFIX_REPX 0x02000000
41 | #define F_PREFIX_REP 0x03000000
42 | #define F_PREFIX_66 0x04000000
43 | #define F_PREFIX_67 0x08000000
44 | #define F_PREFIX_LOCK 0x10000000
45 | #define F_PREFIX_SEG 0x20000000
46 | #define F_PREFIX_REX 0x40000000
47 | #define F_PREFIX_ANY 0x7f000000
48 |
49 | #define PREFIX_SEGMENT_CS 0x2e
50 | #define PREFIX_SEGMENT_SS 0x36
51 | #define PREFIX_SEGMENT_DS 0x3e
52 | #define PREFIX_SEGMENT_ES 0x26
53 | #define PREFIX_SEGMENT_FS 0x64
54 | #define PREFIX_SEGMENT_GS 0x65
55 | #define PREFIX_LOCK 0xf0
56 | #define PREFIX_REPNZ 0xf2
57 | #define PREFIX_REPX 0xf3
58 | #define PREFIX_OPERAND_SIZE 0x66
59 | #define PREFIX_ADDRESS_SIZE 0x67
60 |
61 | #pragma pack(push,1)
62 |
63 | typedef struct {
64 | uint8_t len;
65 | uint8_t p_rep;
66 | uint8_t p_lock;
67 | uint8_t p_seg;
68 | uint8_t p_66;
69 | uint8_t p_67;
70 | uint8_t rex;
71 | uint8_t rex_w;
72 | uint8_t rex_r;
73 | uint8_t rex_x;
74 | uint8_t rex_b;
75 | uint8_t opcode;
76 | uint8_t opcode2;
77 | uint8_t modrm;
78 | uint8_t modrm_mod;
79 | uint8_t modrm_reg;
80 | uint8_t modrm_rm;
81 | uint8_t sib;
82 | uint8_t sib_scale;
83 | uint8_t sib_index;
84 | uint8_t sib_base;
85 | union {
86 | uint8_t imm8;
87 | uint16_t imm16;
88 | uint32_t imm32;
89 | uint64_t imm64;
90 | } imm;
91 | union {
92 | uint8_t disp8;
93 | uint16_t disp16;
94 | uint32_t disp32;
95 | } disp;
96 | uint32_t flags;
97 | } hde64s;
98 |
99 | #pragma pack(pop)
100 |
101 | #ifdef __cplusplus
102 | extern "C" {
103 | #endif
104 |
105 | /* __cdecl */
106 | unsigned int hde64_disasm(const void *code, hde64s *hs);
107 |
108 | #ifdef __cplusplus
109 | }
110 | #endif
111 |
112 | #endif /* _HDE64_H_ */
113 |
--------------------------------------------------------------------------------
/hook.c:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #include
30 | #include
31 | #include
32 |
33 | #include "MinHook.h"
34 | #include "buffer.h"
35 | #include "trampoline.h"
36 |
37 | #ifndef ARRAYSIZE
38 | #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
39 | #endif
40 |
41 | // Initial capacity of the HOOK_ENTRY buffer.
42 | #define INITIAL_HOOK_CAPACITY 32
43 |
44 | // Initial capacity of the thread IDs buffer.
45 | #define INITIAL_THREAD_CAPACITY 128
46 |
47 | // Special hook position values.
48 | #define INVALID_HOOK_POS UINT_MAX
49 | #define ALL_HOOKS_POS UINT_MAX
50 |
51 | // Freeze() action argument defines.
52 | #define ACTION_DISABLE 0
53 | #define ACTION_ENABLE 1
54 | #define ACTION_APPLY_QUEUED 2
55 |
56 | // Thread access rights for suspending/resuming threads.
57 | #define THREAD_ACCESS \
58 | (THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SET_CONTEXT)
59 |
60 | // Hook information.
61 | typedef struct _HOOK_ENTRY
62 | {
63 | LPVOID pTarget; // Address of the target function.
64 | LPVOID pDetour; // Address of the detour or relay function.
65 | LPVOID pTrampoline; // Address of the trampoline function.
66 | UINT8 backup[8]; // Original prologue of the target function.
67 |
68 | UINT8 patchAbove : 1; // Uses the hot patch area.
69 | UINT8 isEnabled : 1; // Enabled.
70 | UINT8 queueEnable : 1; // Queued for enabling/disabling when != isEnabled.
71 |
72 | UINT nIP : 4; // Count of the instruction boundaries.
73 | UINT8 oldIPs[8]; // Instruction boundaries of the target function.
74 | UINT8 newIPs[8]; // Instruction boundaries of the trampoline function.
75 | } HOOK_ENTRY, *PHOOK_ENTRY;
76 |
77 | // Suspended threads for Freeze()/Unfreeze().
78 | typedef struct _FROZEN_THREADS
79 | {
80 | LPDWORD pItems; // Data heap
81 | UINT capacity; // Size of allocated data heap, items
82 | UINT size; // Actual number of data items
83 | } FROZEN_THREADS, *PFROZEN_THREADS;
84 |
85 | //-------------------------------------------------------------------------
86 | // Global Variables:
87 | //-------------------------------------------------------------------------
88 |
89 | // Spin lock flag for EnterSpinLock()/LeaveSpinLock().
90 | volatile LONG g_isLocked = FALSE;
91 |
92 | // Private heap handle. If not NULL, this library is initialized.
93 | HANDLE g_hHeap = NULL;
94 |
95 | // Hook entries.
96 | struct
97 | {
98 | PHOOK_ENTRY pItems; // Data heap
99 | UINT capacity; // Size of allocated data heap, items
100 | UINT size; // Actual number of data items
101 | } g_hooks;
102 |
103 | //-------------------------------------------------------------------------
104 | // Returns INVALID_HOOK_POS if not found.
105 | static UINT FindHookEntry(LPVOID pTarget)
106 | {
107 | UINT i;
108 | for (i = 0; i < g_hooks.size; ++i)
109 | {
110 | if ((ULONG_PTR)pTarget == (ULONG_PTR)g_hooks.pItems[i].pTarget)
111 | return i;
112 | }
113 |
114 | return INVALID_HOOK_POS;
115 | }
116 |
117 | //-------------------------------------------------------------------------
118 | static PHOOK_ENTRY AddHookEntry()
119 | {
120 | if (g_hooks.pItems == NULL)
121 | {
122 | g_hooks.capacity = INITIAL_HOOK_CAPACITY;
123 | g_hooks.pItems = (PHOOK_ENTRY)HeapAlloc(
124 | g_hHeap, 0, g_hooks.capacity * sizeof(HOOK_ENTRY));
125 | if (g_hooks.pItems == NULL)
126 | return NULL;
127 | }
128 | else if (g_hooks.size >= g_hooks.capacity)
129 | {
130 | PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
131 | g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity * 2) * sizeof(HOOK_ENTRY));
132 | if (p == NULL)
133 | return NULL;
134 |
135 | g_hooks.capacity *= 2;
136 | g_hooks.pItems = p;
137 | }
138 |
139 | return &g_hooks.pItems[g_hooks.size++];
140 | }
141 |
142 | //-------------------------------------------------------------------------
143 | static VOID DeleteHookEntry(UINT pos)
144 | {
145 | if (pos < g_hooks.size - 1)
146 | g_hooks.pItems[pos] = g_hooks.pItems[g_hooks.size - 1];
147 |
148 | g_hooks.size--;
149 |
150 | if (g_hooks.capacity / 2 >= INITIAL_HOOK_CAPACITY && g_hooks.capacity / 2 >= g_hooks.size)
151 | {
152 | PHOOK_ENTRY p = (PHOOK_ENTRY)HeapReAlloc(
153 | g_hHeap, 0, g_hooks.pItems, (g_hooks.capacity / 2) * sizeof(HOOK_ENTRY));
154 | if (p == NULL)
155 | return;
156 |
157 | g_hooks.capacity /= 2;
158 | g_hooks.pItems = p;
159 | }
160 | }
161 |
162 | //-------------------------------------------------------------------------
163 | static DWORD_PTR FindOldIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
164 | {
165 | UINT i;
166 |
167 | if (pHook->patchAbove && ip == ((DWORD_PTR)pHook->pTarget - sizeof(JMP_REL)))
168 | return (DWORD_PTR)pHook->pTarget;
169 |
170 | for (i = 0; i < pHook->nIP; ++i)
171 | {
172 | if (ip == ((DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i]))
173 | return (DWORD_PTR)pHook->pTarget + pHook->oldIPs[i];
174 | }
175 |
176 | #if defined(_M_X64) || defined(__x86_64__)
177 | // Check relay function.
178 | if (ip == (DWORD_PTR)pHook->pDetour)
179 | return (DWORD_PTR)pHook->pTarget;
180 | #endif
181 |
182 | return 0;
183 | }
184 |
185 | //-------------------------------------------------------------------------
186 | static DWORD_PTR FindNewIP(PHOOK_ENTRY pHook, DWORD_PTR ip)
187 | {
188 | UINT i;
189 | for (i = 0; i < pHook->nIP; ++i)
190 | {
191 | if (ip == ((DWORD_PTR)pHook->pTarget + pHook->oldIPs[i]))
192 | return (DWORD_PTR)pHook->pTrampoline + pHook->newIPs[i];
193 | }
194 |
195 | return 0;
196 | }
197 |
198 | //-------------------------------------------------------------------------
199 | static VOID ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action)
200 | {
201 | // If the thread suspended in the overwritten area,
202 | // move IP to the proper address.
203 |
204 | CONTEXT c;
205 | #if defined(_M_X64) || defined(__x86_64__)
206 | DWORD64 *pIP = &c.Rip;
207 | #else
208 | DWORD *pIP = &c.Eip;
209 | #endif
210 | UINT count;
211 |
212 | c.ContextFlags = CONTEXT_CONTROL;
213 | if (!GetThreadContext(hThread, &c))
214 | return;
215 |
216 | if (pos == ALL_HOOKS_POS)
217 | {
218 | pos = 0;
219 | count = g_hooks.size;
220 | }
221 | else
222 | {
223 | count = pos + 1;
224 | }
225 |
226 | for (; pos < count; ++pos)
227 | {
228 | PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
229 | BOOL enable;
230 | DWORD_PTR ip;
231 |
232 | switch (action)
233 | {
234 | case ACTION_DISABLE:
235 | enable = FALSE;
236 | break;
237 |
238 | case ACTION_ENABLE:
239 | enable = TRUE;
240 | break;
241 |
242 | default: // ACTION_APPLY_QUEUED
243 | enable = pHook->queueEnable;
244 | break;
245 | }
246 | if (pHook->isEnabled == enable)
247 | continue;
248 |
249 | if (enable)
250 | ip = FindNewIP(pHook, *pIP);
251 | else
252 | ip = FindOldIP(pHook, *pIP);
253 |
254 | if (ip != 0)
255 | {
256 | *pIP = ip;
257 | SetThreadContext(hThread, &c);
258 | }
259 | }
260 | }
261 |
262 | //-------------------------------------------------------------------------
263 | static BOOL EnumerateThreads(PFROZEN_THREADS pThreads)
264 | {
265 | BOOL succeeded = FALSE;
266 |
267 | HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
268 | if (hSnapshot != INVALID_HANDLE_VALUE)
269 | {
270 | THREADENTRY32 te;
271 | te.dwSize = sizeof(THREADENTRY32);
272 | if (Thread32First(hSnapshot, &te))
273 | {
274 | succeeded = TRUE;
275 | do
276 | {
277 | if (te.dwSize >= (FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(DWORD))
278 | && te.th32OwnerProcessID == GetCurrentProcessId()
279 | && te.th32ThreadID != GetCurrentThreadId())
280 | {
281 | if (pThreads->pItems == NULL)
282 | {
283 | pThreads->capacity = INITIAL_THREAD_CAPACITY;
284 | pThreads->pItems
285 | = (LPDWORD)HeapAlloc(g_hHeap, 0, pThreads->capacity * sizeof(DWORD));
286 | if (pThreads->pItems == NULL)
287 | {
288 | succeeded = FALSE;
289 | break;
290 | }
291 | }
292 | else if (pThreads->size >= pThreads->capacity)
293 | {
294 | pThreads->capacity *= 2;
295 | LPDWORD p = (LPDWORD)HeapReAlloc(
296 | g_hHeap, 0, pThreads->pItems, pThreads->capacity * sizeof(DWORD));
297 | if (p == NULL)
298 | {
299 | succeeded = FALSE;
300 | break;
301 | }
302 |
303 | pThreads->pItems = p;
304 | }
305 | pThreads->pItems[pThreads->size++] = te.th32ThreadID;
306 | }
307 |
308 | te.dwSize = sizeof(THREADENTRY32);
309 | } while (Thread32Next(hSnapshot, &te));
310 |
311 | if (succeeded && GetLastError() != ERROR_NO_MORE_FILES)
312 | succeeded = FALSE;
313 |
314 | if (!succeeded && pThreads->pItems != NULL)
315 | {
316 | HeapFree(g_hHeap, 0, pThreads->pItems);
317 | pThreads->pItems = NULL;
318 | }
319 | }
320 | CloseHandle(hSnapshot);
321 | }
322 |
323 | return succeeded;
324 | }
325 |
326 | //-------------------------------------------------------------------------
327 | static MH_STATUS Freeze(PFROZEN_THREADS pThreads, UINT pos, UINT action)
328 | {
329 | MH_STATUS status = MH_OK;
330 |
331 | pThreads->pItems = NULL;
332 | pThreads->capacity = 0;
333 | pThreads->size = 0;
334 | if (!EnumerateThreads(pThreads))
335 | {
336 | status = MH_ERROR_MEMORY_ALLOC;
337 | }
338 | else if (pThreads->pItems != NULL)
339 | {
340 | UINT i;
341 | for (i = 0; i < pThreads->size; ++i)
342 | {
343 | HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
344 | if (hThread != NULL)
345 | {
346 | SuspendThread(hThread);
347 | ProcessThreadIPs(hThread, pos, action);
348 | CloseHandle(hThread);
349 | }
350 | }
351 | }
352 |
353 | return status;
354 | }
355 |
356 | //-------------------------------------------------------------------------
357 | static VOID Unfreeze(PFROZEN_THREADS pThreads)
358 | {
359 | if (pThreads->pItems != NULL)
360 | {
361 | UINT i;
362 | for (i = 0; i < pThreads->size; ++i)
363 | {
364 | HANDLE hThread = OpenThread(THREAD_ACCESS, FALSE, pThreads->pItems[i]);
365 | if (hThread != NULL)
366 | {
367 | ResumeThread(hThread);
368 | CloseHandle(hThread);
369 | }
370 | }
371 |
372 | HeapFree(g_hHeap, 0, pThreads->pItems);
373 | }
374 | }
375 |
376 | //-------------------------------------------------------------------------
377 | static MH_STATUS EnableHookLL(UINT pos, BOOL enable)
378 | {
379 | PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
380 | DWORD oldProtect;
381 | SIZE_T patchSize = sizeof(JMP_REL);
382 | LPBYTE pPatchTarget = (LPBYTE)pHook->pTarget;
383 |
384 | if (pHook->patchAbove)
385 | {
386 | pPatchTarget -= sizeof(JMP_REL);
387 | patchSize += sizeof(JMP_REL_SHORT);
388 | }
389 |
390 | if (!VirtualProtect(pPatchTarget, patchSize, PAGE_EXECUTE_READWRITE, &oldProtect))
391 | return MH_ERROR_MEMORY_PROTECT;
392 |
393 | if (enable)
394 | {
395 | PJMP_REL pJmp = (PJMP_REL)pPatchTarget;
396 | pJmp->opcode = 0xE9;
397 | pJmp->operand = (UINT32)((LPBYTE)pHook->pDetour - (pPatchTarget + sizeof(JMP_REL)));
398 |
399 | if (pHook->patchAbove)
400 | {
401 | PJMP_REL_SHORT pShortJmp = (PJMP_REL_SHORT)pHook->pTarget;
402 | pShortJmp->opcode = 0xEB;
403 | pShortJmp->operand = (UINT8)(0 - (sizeof(JMP_REL_SHORT) + sizeof(JMP_REL)));
404 | }
405 | }
406 | else
407 | {
408 | if (pHook->patchAbove)
409 | memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
410 | else
411 | memcpy(pPatchTarget, pHook->backup, sizeof(JMP_REL));
412 | }
413 |
414 | VirtualProtect(pPatchTarget, patchSize, oldProtect, &oldProtect);
415 |
416 | // Just-in-case measure.
417 | FlushInstructionCache(GetCurrentProcess(), pPatchTarget, patchSize);
418 |
419 | pHook->isEnabled = enable;
420 | pHook->queueEnable = enable;
421 |
422 | return MH_OK;
423 | }
424 |
425 | //-------------------------------------------------------------------------
426 | static MH_STATUS EnableAllHooksLL(BOOL enable)
427 | {
428 | MH_STATUS status = MH_OK;
429 | UINT i, first = INVALID_HOOK_POS;
430 |
431 | for (i = 0; i < g_hooks.size; ++i)
432 | {
433 | if (g_hooks.pItems[i].isEnabled != enable)
434 | {
435 | first = i;
436 | break;
437 | }
438 | }
439 |
440 | if (first != INVALID_HOOK_POS)
441 | {
442 | FROZEN_THREADS threads;
443 | status = Freeze(&threads, ALL_HOOKS_POS, enable ? ACTION_ENABLE : ACTION_DISABLE);
444 | if (status == MH_OK)
445 | {
446 | for (i = first; i < g_hooks.size; ++i)
447 | {
448 | if (g_hooks.pItems[i].isEnabled != enable)
449 | {
450 | status = EnableHookLL(i, enable);
451 | if (status != MH_OK)
452 | break;
453 | }
454 | }
455 |
456 | Unfreeze(&threads);
457 | }
458 | }
459 |
460 | return status;
461 | }
462 |
463 | //-------------------------------------------------------------------------
464 | static VOID EnterSpinLock(VOID)
465 | {
466 | SIZE_T spinCount = 0;
467 |
468 | // Wait until the flag is FALSE.
469 | while (InterlockedCompareExchange(&g_isLocked, TRUE, FALSE) != FALSE)
470 | {
471 | // No need to generate a memory barrier here, since InterlockedCompareExchange()
472 | // generates a full memory barrier itself.
473 |
474 | // Prevent the loop from being too busy.
475 | if (spinCount < 32)
476 | Sleep(0);
477 | else
478 | Sleep(1);
479 |
480 | spinCount++;
481 | }
482 | }
483 |
484 | //-------------------------------------------------------------------------
485 | static VOID LeaveSpinLock(VOID)
486 | {
487 | // No need to generate a memory barrier here, since InterlockedExchange()
488 | // generates a full memory barrier itself.
489 |
490 | InterlockedExchange(&g_isLocked, FALSE);
491 | }
492 |
493 | //-------------------------------------------------------------------------
494 | MH_STATUS WINAPI MH_Initialize(VOID)
495 | {
496 | MH_STATUS status = MH_OK;
497 |
498 | EnterSpinLock();
499 |
500 | if (g_hHeap == NULL)
501 | {
502 | g_hHeap = HeapCreate(0, 0, 0);
503 | if (g_hHeap != NULL)
504 | {
505 | // Initialize the internal function buffer.
506 | InitializeBuffer();
507 | }
508 | else
509 | {
510 | status = MH_ERROR_MEMORY_ALLOC;
511 | }
512 | }
513 | else
514 | {
515 | status = MH_ERROR_ALREADY_INITIALIZED;
516 | }
517 |
518 | LeaveSpinLock();
519 |
520 | return status;
521 | }
522 |
523 | //-------------------------------------------------------------------------
524 | MH_STATUS WINAPI MH_Uninitialize(VOID)
525 | {
526 | MH_STATUS status = MH_OK;
527 |
528 | EnterSpinLock();
529 |
530 | if (g_hHeap != NULL)
531 | {
532 | status = EnableAllHooksLL(FALSE);
533 | if (status == MH_OK)
534 | {
535 | // Free the internal function buffer.
536 |
537 | // HeapFree is actually not required, but some tools detect a false
538 | // memory leak without HeapFree.
539 |
540 | UninitializeBuffer();
541 |
542 | HeapFree(g_hHeap, 0, g_hooks.pItems);
543 | HeapDestroy(g_hHeap);
544 |
545 | g_hHeap = NULL;
546 |
547 | g_hooks.pItems = NULL;
548 | g_hooks.capacity = 0;
549 | g_hooks.size = 0;
550 | }
551 | }
552 | else
553 | {
554 | status = MH_ERROR_NOT_INITIALIZED;
555 | }
556 |
557 | LeaveSpinLock();
558 |
559 | return status;
560 | }
561 |
562 | //-------------------------------------------------------------------------
563 | MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal)
564 | {
565 | MH_STATUS status = MH_OK;
566 |
567 | EnterSpinLock();
568 |
569 | if (g_hHeap != NULL)
570 | {
571 | if (IsExecutableAddress(pTarget) && IsExecutableAddress(pDetour))
572 | {
573 | UINT pos = FindHookEntry(pTarget);
574 | if (pos == INVALID_HOOK_POS)
575 | {
576 | LPVOID pBuffer = AllocateBuffer(pTarget);
577 | if (pBuffer != NULL)
578 | {
579 | TRAMPOLINE ct;
580 |
581 | ct.pTarget = pTarget;
582 | ct.pDetour = pDetour;
583 | ct.pTrampoline = pBuffer;
584 | if (CreateTrampolineFunction(&ct))
585 | {
586 | PHOOK_ENTRY pHook = AddHookEntry();
587 | if (pHook != NULL)
588 | {
589 | pHook->pTarget = ct.pTarget;
590 | #if defined(_M_X64) || defined(__x86_64__)
591 | pHook->pDetour = ct.pRelay;
592 | #else
593 | pHook->pDetour = ct.pDetour;
594 | #endif
595 | pHook->pTrampoline = ct.pTrampoline;
596 | pHook->patchAbove = ct.patchAbove;
597 | pHook->isEnabled = FALSE;
598 | pHook->queueEnable = FALSE;
599 | pHook->nIP = ct.nIP;
600 | memcpy(pHook->oldIPs, ct.oldIPs, ARRAYSIZE(ct.oldIPs));
601 | memcpy(pHook->newIPs, ct.newIPs, ARRAYSIZE(ct.newIPs));
602 |
603 | // Back up the target function.
604 |
605 | if (ct.patchAbove)
606 | {
607 | memcpy(
608 | pHook->backup,
609 | (LPBYTE)pTarget - sizeof(JMP_REL),
610 | sizeof(JMP_REL) + sizeof(JMP_REL_SHORT));
611 | }
612 | else
613 | {
614 | memcpy(pHook->backup, pTarget, sizeof(JMP_REL));
615 | }
616 |
617 | if (ppOriginal != NULL)
618 | *ppOriginal = pHook->pTrampoline;
619 | }
620 | else
621 | {
622 | status = MH_ERROR_MEMORY_ALLOC;
623 | }
624 | }
625 | else
626 | {
627 | status = MH_ERROR_UNSUPPORTED_FUNCTION;
628 | }
629 |
630 | if (status != MH_OK)
631 | {
632 | FreeBuffer(pBuffer);
633 | }
634 | }
635 | else
636 | {
637 | status = MH_ERROR_MEMORY_ALLOC;
638 | }
639 | }
640 | else
641 | {
642 | status = MH_ERROR_ALREADY_CREATED;
643 | }
644 | }
645 | else
646 | {
647 | status = MH_ERROR_NOT_EXECUTABLE;
648 | }
649 | }
650 | else
651 | {
652 | status = MH_ERROR_NOT_INITIALIZED;
653 | }
654 |
655 | LeaveSpinLock();
656 |
657 | return status;
658 | }
659 |
660 | //-------------------------------------------------------------------------
661 | MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget)
662 | {
663 | MH_STATUS status = MH_OK;
664 |
665 | EnterSpinLock();
666 |
667 | if (g_hHeap != NULL)
668 | {
669 | UINT pos = FindHookEntry(pTarget);
670 | if (pos != INVALID_HOOK_POS)
671 | {
672 | if (g_hooks.pItems[pos].isEnabled)
673 | {
674 | FROZEN_THREADS threads;
675 | status = Freeze(&threads, pos, ACTION_DISABLE);
676 | if (status == MH_OK)
677 | {
678 | status = EnableHookLL(pos, FALSE);
679 |
680 | Unfreeze(&threads);
681 | }
682 | }
683 |
684 | if (status == MH_OK)
685 | {
686 | FreeBuffer(g_hooks.pItems[pos].pTrampoline);
687 | DeleteHookEntry(pos);
688 | }
689 | }
690 | else
691 | {
692 | status = MH_ERROR_NOT_CREATED;
693 | }
694 | }
695 | else
696 | {
697 | status = MH_ERROR_NOT_INITIALIZED;
698 | }
699 |
700 | LeaveSpinLock();
701 |
702 | return status;
703 | }
704 |
705 | //-------------------------------------------------------------------------
706 | static MH_STATUS EnableHook(LPVOID pTarget, BOOL enable)
707 | {
708 | MH_STATUS status = MH_OK;
709 |
710 | EnterSpinLock();
711 |
712 | if (g_hHeap != NULL)
713 | {
714 | if (pTarget == MH_ALL_HOOKS)
715 | {
716 | status = EnableAllHooksLL(enable);
717 | }
718 | else
719 | {
720 | UINT pos = FindHookEntry(pTarget);
721 | if (pos != INVALID_HOOK_POS)
722 | {
723 | if (g_hooks.pItems[pos].isEnabled != enable)
724 | {
725 | FROZEN_THREADS threads;
726 | status = Freeze(&threads, pos, ACTION_ENABLE);
727 | if (status == MH_OK)
728 | {
729 | status = EnableHookLL(pos, enable);
730 |
731 | Unfreeze(&threads);
732 | }
733 | }
734 | else
735 | {
736 | status = enable ? MH_ERROR_ENABLED : MH_ERROR_DISABLED;
737 | }
738 | }
739 | else
740 | {
741 | status = MH_ERROR_NOT_CREATED;
742 | }
743 | }
744 | }
745 | else
746 | {
747 | status = MH_ERROR_NOT_INITIALIZED;
748 | }
749 |
750 | LeaveSpinLock();
751 |
752 | return status;
753 | }
754 |
755 | //-------------------------------------------------------------------------
756 | MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget)
757 | {
758 | return EnableHook(pTarget, TRUE);
759 | }
760 |
761 | //-------------------------------------------------------------------------
762 | MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget)
763 | {
764 | return EnableHook(pTarget, FALSE);
765 | }
766 |
767 | //-------------------------------------------------------------------------
768 | static MH_STATUS QueueHook(LPVOID pTarget, BOOL queueEnable)
769 | {
770 | MH_STATUS status = MH_OK;
771 |
772 | EnterSpinLock();
773 |
774 | if (g_hHeap != NULL)
775 | {
776 | if (pTarget == MH_ALL_HOOKS)
777 | {
778 | UINT i;
779 | for (i = 0; i < g_hooks.size; ++i)
780 | g_hooks.pItems[i].queueEnable = queueEnable;
781 | }
782 | else
783 | {
784 | UINT pos = FindHookEntry(pTarget);
785 | if (pos != INVALID_HOOK_POS)
786 | {
787 | g_hooks.pItems[pos].queueEnable = queueEnable;
788 | }
789 | else
790 | {
791 | status = MH_ERROR_NOT_CREATED;
792 | }
793 | }
794 | }
795 | else
796 | {
797 | status = MH_ERROR_NOT_INITIALIZED;
798 | }
799 |
800 | LeaveSpinLock();
801 |
802 | return status;
803 | }
804 |
805 | //-------------------------------------------------------------------------
806 | MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget)
807 | {
808 | return QueueHook(pTarget, TRUE);
809 | }
810 |
811 | //-------------------------------------------------------------------------
812 | MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget)
813 | {
814 | return QueueHook(pTarget, FALSE);
815 | }
816 |
817 | //-------------------------------------------------------------------------
818 | MH_STATUS WINAPI MH_ApplyQueued(VOID)
819 | {
820 | MH_STATUS status = MH_OK;
821 | UINT i, first = INVALID_HOOK_POS;
822 |
823 | EnterSpinLock();
824 |
825 | if (g_hHeap != NULL)
826 | {
827 | for (i = 0; i < g_hooks.size; ++i)
828 | {
829 | if (g_hooks.pItems[i].isEnabled != g_hooks.pItems[i].queueEnable)
830 | {
831 | first = i;
832 | break;
833 | }
834 | }
835 |
836 | if (first != INVALID_HOOK_POS)
837 | {
838 | FROZEN_THREADS threads;
839 | status = Freeze(&threads, ALL_HOOKS_POS, ACTION_APPLY_QUEUED);
840 | if (status == MH_OK)
841 | {
842 | for (i = first; i < g_hooks.size; ++i)
843 | {
844 | PHOOK_ENTRY pHook = &g_hooks.pItems[i];
845 | if (pHook->isEnabled != pHook->queueEnable)
846 | {
847 | status = EnableHookLL(i, pHook->queueEnable);
848 | if (status != MH_OK)
849 | break;
850 | }
851 | }
852 |
853 | Unfreeze(&threads);
854 | }
855 | }
856 | }
857 | else
858 | {
859 | status = MH_ERROR_NOT_INITIALIZED;
860 | }
861 |
862 | LeaveSpinLock();
863 |
864 | return status;
865 | }
866 |
867 | //-------------------------------------------------------------------------
868 | MH_STATUS WINAPI MH_CreateHookApiEx(
869 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour,
870 | LPVOID *ppOriginal, LPVOID *ppTarget)
871 | {
872 | HMODULE hModule;
873 | LPVOID pTarget;
874 |
875 | hModule = GetModuleHandleW(pszModule);
876 | if (hModule == NULL)
877 | return MH_ERROR_MODULE_NOT_FOUND;
878 |
879 | pTarget = (LPVOID)GetProcAddress(hModule, pszProcName);
880 | if (pTarget == NULL)
881 | return MH_ERROR_FUNCTION_NOT_FOUND;
882 |
883 | if(ppTarget != NULL)
884 | *ppTarget = pTarget;
885 |
886 | return MH_CreateHook(pTarget, pDetour, ppOriginal);
887 | }
888 |
889 | //-------------------------------------------------------------------------
890 | MH_STATUS WINAPI MH_CreateHookApi(
891 | LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal)
892 | {
893 | return MH_CreateHookApiEx(pszModule, pszProcName, pDetour, ppOriginal, NULL);
894 | }
895 |
896 | //-------------------------------------------------------------------------
897 | const char * WINAPI MH_StatusToString(MH_STATUS status)
898 | {
899 | #define MH_ST2STR(x) \
900 | case x: \
901 | return #x;
902 |
903 | switch (status) {
904 | MH_ST2STR(MH_UNKNOWN)
905 | MH_ST2STR(MH_OK)
906 | MH_ST2STR(MH_ERROR_ALREADY_INITIALIZED)
907 | MH_ST2STR(MH_ERROR_NOT_INITIALIZED)
908 | MH_ST2STR(MH_ERROR_ALREADY_CREATED)
909 | MH_ST2STR(MH_ERROR_NOT_CREATED)
910 | MH_ST2STR(MH_ERROR_ENABLED)
911 | MH_ST2STR(MH_ERROR_DISABLED)
912 | MH_ST2STR(MH_ERROR_NOT_EXECUTABLE)
913 | MH_ST2STR(MH_ERROR_UNSUPPORTED_FUNCTION)
914 | MH_ST2STR(MH_ERROR_MEMORY_ALLOC)
915 | MH_ST2STR(MH_ERROR_MEMORY_PROTECT)
916 | MH_ST2STR(MH_ERROR_MODULE_NOT_FOUND)
917 | MH_ST2STR(MH_ERROR_FUNCTION_NOT_FOUND)
918 | }
919 |
920 | #undef MH_ST2STR
921 |
922 | return "(unknown)";
923 | }
924 |
--------------------------------------------------------------------------------
/jni.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
3 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4 | *
5 | *
6 | *
7 | *
8 | *
9 | *
10 | *
11 | *
12 | *
13 | *
14 | *
15 | *
16 | *
17 | *
18 | *
19 | *
20 | *
21 | *
22 | *
23 | *
24 | */
25 |
26 | /*
27 | * We used part of Netscape's Java Runtime Interface (JRI) as the starting
28 | * point of our design and implementation.
29 | */
30 |
31 | /******************************************************************************
32 | * Java Runtime Interface
33 | * Copyright (c) 1996 Netscape Communications Corporation. All rights reserved.
34 | *****************************************************************************/
35 |
36 | #ifndef _JAVASOFT_JNI_H_
37 | #define _JAVASOFT_JNI_H_
38 |
39 | #include
40 | #include
41 |
42 | /* jni_md.h contains the machine-dependent typedefs for jbyte, jint
43 | and jlong */
44 |
45 | #include "jni_md.h"
46 |
47 | #ifdef __cplusplus
48 | extern "C" {
49 | #endif
50 |
51 | /*
52 | * JNI Types
53 | */
54 |
55 | #ifndef JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
56 |
57 | typedef unsigned char jboolean;
58 | typedef unsigned short jchar;
59 | typedef short jshort;
60 | typedef float jfloat;
61 | typedef double jdouble;
62 |
63 | typedef jint jsize;
64 |
65 | #ifdef __cplusplus
66 |
67 | class _jobject {};
68 | class _jclass : public _jobject {};
69 | class _jthrowable : public _jobject {};
70 | class _jstring : public _jobject {};
71 | class _jarray : public _jobject {};
72 | class _jbooleanArray : public _jarray {};
73 | class _jbyteArray : public _jarray {};
74 | class _jcharArray : public _jarray {};
75 | class _jshortArray : public _jarray {};
76 | class _jintArray : public _jarray {};
77 | class _jlongArray : public _jarray {};
78 | class _jfloatArray : public _jarray {};
79 | class _jdoubleArray : public _jarray {};
80 | class _jobjectArray : public _jarray {};
81 |
82 | typedef _jobject *jobject;
83 | typedef _jclass *jclass;
84 | typedef _jthrowable *jthrowable;
85 | typedef _jstring *jstring;
86 | typedef _jarray *jarray;
87 | typedef _jbooleanArray *jbooleanArray;
88 | typedef _jbyteArray *jbyteArray;
89 | typedef _jcharArray *jcharArray;
90 | typedef _jshortArray *jshortArray;
91 | typedef _jintArray *jintArray;
92 | typedef _jlongArray *jlongArray;
93 | typedef _jfloatArray *jfloatArray;
94 | typedef _jdoubleArray *jdoubleArray;
95 | typedef _jobjectArray *jobjectArray;
96 |
97 | #else
98 |
99 | struct _jobject;
100 |
101 | typedef struct _jobject *jobject;
102 | typedef jobject jclass;
103 | typedef jobject jthrowable;
104 | typedef jobject jstring;
105 | typedef jobject jarray;
106 | typedef jarray jbooleanArray;
107 | typedef jarray jbyteArray;
108 | typedef jarray jcharArray;
109 | typedef jarray jshortArray;
110 | typedef jarray jintArray;
111 | typedef jarray jlongArray;
112 | typedef jarray jfloatArray;
113 | typedef jarray jdoubleArray;
114 | typedef jarray jobjectArray;
115 |
116 | #endif
117 |
118 | typedef jobject jweak;
119 |
120 | typedef union jvalue {
121 | jboolean z;
122 | jbyte b;
123 | jchar c;
124 | jshort s;
125 | jint i;
126 | jlong j;
127 | jfloat f;
128 | jdouble d;
129 | jobject l;
130 | } jvalue;
131 |
132 | struct _jfieldID;
133 | typedef struct _jfieldID *jfieldID;
134 |
135 | struct _jmethodID;
136 | typedef struct _jmethodID *jmethodID;
137 |
138 | /* Return values from jobjectRefType */
139 | typedef enum _jobjectType {
140 | JNIInvalidRefType = 0,
141 | JNILocalRefType = 1,
142 | JNIGlobalRefType = 2,
143 | JNIWeakGlobalRefType = 3
144 | } jobjectRefType;
145 |
146 |
147 | #endif /* JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H */
148 |
149 | /*
150 | * jboolean constants
151 | */
152 |
153 | #define JNI_FALSE 0
154 | #define JNI_TRUE 1
155 |
156 | /*
157 | * possible return values for JNI functions.
158 | */
159 |
160 | #define JNI_OK 0 /* success */
161 | #define JNI_ERR (-1) /* unknown error */
162 | #define JNI_EDETACHED (-2) /* thread detached from the VM */
163 | #define JNI_EVERSION (-3) /* JNI version error */
164 | #define JNI_ENOMEM (-4) /* not enough memory */
165 | #define JNI_EEXIST (-5) /* VM already created */
166 | #define JNI_EINVAL (-6) /* invalid arguments */
167 |
168 | /*
169 | * used in ReleaseScalarArrayElements
170 | */
171 |
172 | #define JNI_COMMIT 1
173 | #define JNI_ABORT 2
174 |
175 | /*
176 | * used in RegisterNatives to describe native method name, signature,
177 | * and function pointer.
178 | */
179 |
180 | typedef struct {
181 | char *name;
182 | char *signature;
183 | void *fnPtr;
184 | } JNINativeMethod;
185 |
186 | /*
187 | * JNI Native Method Interface.
188 | */
189 |
190 | struct JNINativeInterface_;
191 |
192 | struct JNIEnv_;
193 |
194 | #ifdef __cplusplus
195 | typedef JNIEnv_ JNIEnv;
196 | #else
197 | typedef const struct JNINativeInterface_ *JNIEnv;
198 | #endif
199 |
200 | /*
201 | * JNI Invocation Interface.
202 | */
203 |
204 | struct JNIInvokeInterface_;
205 |
206 | struct JavaVM_;
207 |
208 | #ifdef __cplusplus
209 | typedef JavaVM_ JavaVM;
210 | #else
211 | typedef const struct JNIInvokeInterface_ *JavaVM;
212 | #endif
213 |
214 | struct JNINativeInterface_ {
215 | void *reserved0;
216 | void *reserved1;
217 | void *reserved2;
218 |
219 | void *reserved3;
220 | jint (JNICALL *GetVersion)(JNIEnv *env);
221 |
222 | jclass (JNICALL *DefineClass)
223 | (JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
224 | jsize len);
225 | jclass (JNICALL *FindClass)
226 | (JNIEnv *env, const char *name);
227 |
228 | jmethodID (JNICALL *FromReflectedMethod)
229 | (JNIEnv *env, jobject method);
230 | jfieldID (JNICALL *FromReflectedField)
231 | (JNIEnv *env, jobject field);
232 |
233 | jobject (JNICALL *ToReflectedMethod)
234 | (JNIEnv *env, jclass cls, jmethodID methodID, jboolean isStatic);
235 |
236 | jclass (JNICALL *GetSuperclass)
237 | (JNIEnv *env, jclass sub);
238 | jboolean (JNICALL *IsAssignableFrom)
239 | (JNIEnv *env, jclass sub, jclass sup);
240 |
241 | jobject (JNICALL *ToReflectedField)
242 | (JNIEnv *env, jclass cls, jfieldID fieldID, jboolean isStatic);
243 |
244 | jint (JNICALL *Throw)
245 | (JNIEnv *env, jthrowable obj);
246 | jint (JNICALL *ThrowNew)
247 | (JNIEnv *env, jclass clazz, const char *msg);
248 | jthrowable (JNICALL *ExceptionOccurred)
249 | (JNIEnv *env);
250 | void (JNICALL *ExceptionDescribe)
251 | (JNIEnv *env);
252 | void (JNICALL *ExceptionClear)
253 | (JNIEnv *env);
254 | void (JNICALL *FatalError)
255 | (JNIEnv *env, const char *msg);
256 |
257 | jint (JNICALL *PushLocalFrame)
258 | (JNIEnv *env, jint capacity);
259 | jobject (JNICALL *PopLocalFrame)
260 | (JNIEnv *env, jobject result);
261 |
262 | jobject (JNICALL *NewGlobalRef)
263 | (JNIEnv *env, jobject lobj);
264 | void (JNICALL *DeleteGlobalRef)
265 | (JNIEnv *env, jobject gref);
266 | void (JNICALL *DeleteLocalRef)
267 | (JNIEnv *env, jobject obj);
268 | jboolean (JNICALL *IsSameObject)
269 | (JNIEnv *env, jobject obj1, jobject obj2);
270 | jobject (JNICALL *NewLocalRef)
271 | (JNIEnv *env, jobject ref);
272 | jint (JNICALL *EnsureLocalCapacity)
273 | (JNIEnv *env, jint capacity);
274 |
275 | jobject (JNICALL *AllocObject)
276 | (JNIEnv *env, jclass clazz);
277 | jobject (JNICALL *NewObject)
278 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
279 | jobject (JNICALL *NewObjectV)
280 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
281 | jobject (JNICALL *NewObjectA)
282 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
283 |
284 | jclass (JNICALL *GetObjectClass)
285 | (JNIEnv *env, jobject obj);
286 | jboolean (JNICALL *IsInstanceOf)
287 | (JNIEnv *env, jobject obj, jclass clazz);
288 |
289 | jmethodID (JNICALL *GetMethodID)
290 | (JNIEnv *env, jclass clazz, const char *name, const char *sig);
291 |
292 | jobject (JNICALL *CallObjectMethod)
293 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
294 | jobject (JNICALL *CallObjectMethodV)
295 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
296 | jobject (JNICALL *CallObjectMethodA)
297 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
298 |
299 | jboolean (JNICALL *CallBooleanMethod)
300 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
301 | jboolean (JNICALL *CallBooleanMethodV)
302 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
303 | jboolean (JNICALL *CallBooleanMethodA)
304 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
305 |
306 | jbyte (JNICALL *CallByteMethod)
307 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
308 | jbyte (JNICALL *CallByteMethodV)
309 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
310 | jbyte (JNICALL *CallByteMethodA)
311 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
312 |
313 | jchar (JNICALL *CallCharMethod)
314 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
315 | jchar (JNICALL *CallCharMethodV)
316 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
317 | jchar (JNICALL *CallCharMethodA)
318 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
319 |
320 | jshort (JNICALL *CallShortMethod)
321 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
322 | jshort (JNICALL *CallShortMethodV)
323 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
324 | jshort (JNICALL *CallShortMethodA)
325 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
326 |
327 | jint (JNICALL *CallIntMethod)
328 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
329 | jint (JNICALL *CallIntMethodV)
330 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
331 | jint (JNICALL *CallIntMethodA)
332 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
333 |
334 | jlong (JNICALL *CallLongMethod)
335 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
336 | jlong (JNICALL *CallLongMethodV)
337 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
338 | jlong (JNICALL *CallLongMethodA)
339 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
340 |
341 | jfloat (JNICALL *CallFloatMethod)
342 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
343 | jfloat (JNICALL *CallFloatMethodV)
344 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
345 | jfloat (JNICALL *CallFloatMethodA)
346 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
347 |
348 | jdouble (JNICALL *CallDoubleMethod)
349 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
350 | jdouble (JNICALL *CallDoubleMethodV)
351 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
352 | jdouble (JNICALL *CallDoubleMethodA)
353 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue *args);
354 |
355 | void (JNICALL *CallVoidMethod)
356 | (JNIEnv *env, jobject obj, jmethodID methodID, ...);
357 | void (JNICALL *CallVoidMethodV)
358 | (JNIEnv *env, jobject obj, jmethodID methodID, va_list args);
359 | void (JNICALL *CallVoidMethodA)
360 | (JNIEnv *env, jobject obj, jmethodID methodID, const jvalue * args);
361 |
362 | jobject (JNICALL *CallNonvirtualObjectMethod)
363 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
364 | jobject (JNICALL *CallNonvirtualObjectMethodV)
365 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
366 | va_list args);
367 | jobject (JNICALL *CallNonvirtualObjectMethodA)
368 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
369 | const jvalue * args);
370 |
371 | jboolean (JNICALL *CallNonvirtualBooleanMethod)
372 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
373 | jboolean (JNICALL *CallNonvirtualBooleanMethodV)
374 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
375 | va_list args);
376 | jboolean (JNICALL *CallNonvirtualBooleanMethodA)
377 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
378 | const jvalue * args);
379 |
380 | jbyte (JNICALL *CallNonvirtualByteMethod)
381 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
382 | jbyte (JNICALL *CallNonvirtualByteMethodV)
383 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
384 | va_list args);
385 | jbyte (JNICALL *CallNonvirtualByteMethodA)
386 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
387 | const jvalue *args);
388 |
389 | jchar (JNICALL *CallNonvirtualCharMethod)
390 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
391 | jchar (JNICALL *CallNonvirtualCharMethodV)
392 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
393 | va_list args);
394 | jchar (JNICALL *CallNonvirtualCharMethodA)
395 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
396 | const jvalue *args);
397 |
398 | jshort (JNICALL *CallNonvirtualShortMethod)
399 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
400 | jshort (JNICALL *CallNonvirtualShortMethodV)
401 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
402 | va_list args);
403 | jshort (JNICALL *CallNonvirtualShortMethodA)
404 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
405 | const jvalue *args);
406 |
407 | jint (JNICALL *CallNonvirtualIntMethod)
408 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
409 | jint (JNICALL *CallNonvirtualIntMethodV)
410 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
411 | va_list args);
412 | jint (JNICALL *CallNonvirtualIntMethodA)
413 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
414 | const jvalue *args);
415 |
416 | jlong (JNICALL *CallNonvirtualLongMethod)
417 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
418 | jlong (JNICALL *CallNonvirtualLongMethodV)
419 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
420 | va_list args);
421 | jlong (JNICALL *CallNonvirtualLongMethodA)
422 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
423 | const jvalue *args);
424 |
425 | jfloat (JNICALL *CallNonvirtualFloatMethod)
426 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
427 | jfloat (JNICALL *CallNonvirtualFloatMethodV)
428 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
429 | va_list args);
430 | jfloat (JNICALL *CallNonvirtualFloatMethodA)
431 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
432 | const jvalue *args);
433 |
434 | jdouble (JNICALL *CallNonvirtualDoubleMethod)
435 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
436 | jdouble (JNICALL *CallNonvirtualDoubleMethodV)
437 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
438 | va_list args);
439 | jdouble (JNICALL *CallNonvirtualDoubleMethodA)
440 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
441 | const jvalue *args);
442 |
443 | void (JNICALL *CallNonvirtualVoidMethod)
444 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID, ...);
445 | void (JNICALL *CallNonvirtualVoidMethodV)
446 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
447 | va_list args);
448 | void (JNICALL *CallNonvirtualVoidMethodA)
449 | (JNIEnv *env, jobject obj, jclass clazz, jmethodID methodID,
450 | const jvalue * args);
451 |
452 | jfieldID (JNICALL *GetFieldID)
453 | (JNIEnv *env, jclass clazz, const char *name, const char *sig);
454 |
455 | jobject (JNICALL *GetObjectField)
456 | (JNIEnv *env, jobject obj, jfieldID fieldID);
457 | jboolean (JNICALL *GetBooleanField)
458 | (JNIEnv *env, jobject obj, jfieldID fieldID);
459 | jbyte (JNICALL *GetByteField)
460 | (JNIEnv *env, jobject obj, jfieldID fieldID);
461 | jchar (JNICALL *GetCharField)
462 | (JNIEnv *env, jobject obj, jfieldID fieldID);
463 | jshort (JNICALL *GetShortField)
464 | (JNIEnv *env, jobject obj, jfieldID fieldID);
465 | jint (JNICALL *GetIntField)
466 | (JNIEnv *env, jobject obj, jfieldID fieldID);
467 | jlong (JNICALL *GetLongField)
468 | (JNIEnv *env, jobject obj, jfieldID fieldID);
469 | jfloat (JNICALL *GetFloatField)
470 | (JNIEnv *env, jobject obj, jfieldID fieldID);
471 | jdouble (JNICALL *GetDoubleField)
472 | (JNIEnv *env, jobject obj, jfieldID fieldID);
473 |
474 | void (JNICALL *SetObjectField)
475 | (JNIEnv *env, jobject obj, jfieldID fieldID, jobject val);
476 | void (JNICALL *SetBooleanField)
477 | (JNIEnv *env, jobject obj, jfieldID fieldID, jboolean val);
478 | void (JNICALL *SetByteField)
479 | (JNIEnv *env, jobject obj, jfieldID fieldID, jbyte val);
480 | void (JNICALL *SetCharField)
481 | (JNIEnv *env, jobject obj, jfieldID fieldID, jchar val);
482 | void (JNICALL *SetShortField)
483 | (JNIEnv *env, jobject obj, jfieldID fieldID, jshort val);
484 | void (JNICALL *SetIntField)
485 | (JNIEnv *env, jobject obj, jfieldID fieldID, jint val);
486 | void (JNICALL *SetLongField)
487 | (JNIEnv *env, jobject obj, jfieldID fieldID, jlong val);
488 | void (JNICALL *SetFloatField)
489 | (JNIEnv *env, jobject obj, jfieldID fieldID, jfloat val);
490 | void (JNICALL *SetDoubleField)
491 | (JNIEnv *env, jobject obj, jfieldID fieldID, jdouble val);
492 |
493 | jmethodID (JNICALL *GetStaticMethodID)
494 | (JNIEnv *env, jclass clazz, const char *name, const char *sig);
495 |
496 | jobject (JNICALL *CallStaticObjectMethod)
497 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
498 | jobject (JNICALL *CallStaticObjectMethodV)
499 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
500 | jobject (JNICALL *CallStaticObjectMethodA)
501 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
502 |
503 | jboolean (JNICALL *CallStaticBooleanMethod)
504 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
505 | jboolean (JNICALL *CallStaticBooleanMethodV)
506 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
507 | jboolean (JNICALL *CallStaticBooleanMethodA)
508 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
509 |
510 | jbyte (JNICALL *CallStaticByteMethod)
511 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
512 | jbyte (JNICALL *CallStaticByteMethodV)
513 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
514 | jbyte (JNICALL *CallStaticByteMethodA)
515 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
516 |
517 | jchar (JNICALL *CallStaticCharMethod)
518 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
519 | jchar (JNICALL *CallStaticCharMethodV)
520 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
521 | jchar (JNICALL *CallStaticCharMethodA)
522 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
523 |
524 | jshort (JNICALL *CallStaticShortMethod)
525 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
526 | jshort (JNICALL *CallStaticShortMethodV)
527 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
528 | jshort (JNICALL *CallStaticShortMethodA)
529 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
530 |
531 | jint (JNICALL *CallStaticIntMethod)
532 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
533 | jint (JNICALL *CallStaticIntMethodV)
534 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
535 | jint (JNICALL *CallStaticIntMethodA)
536 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
537 |
538 | jlong (JNICALL *CallStaticLongMethod)
539 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
540 | jlong (JNICALL *CallStaticLongMethodV)
541 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
542 | jlong (JNICALL *CallStaticLongMethodA)
543 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
544 |
545 | jfloat (JNICALL *CallStaticFloatMethod)
546 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
547 | jfloat (JNICALL *CallStaticFloatMethodV)
548 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
549 | jfloat (JNICALL *CallStaticFloatMethodA)
550 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
551 |
552 | jdouble (JNICALL *CallStaticDoubleMethod)
553 | (JNIEnv *env, jclass clazz, jmethodID methodID, ...);
554 | jdouble (JNICALL *CallStaticDoubleMethodV)
555 | (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args);
556 | jdouble (JNICALL *CallStaticDoubleMethodA)
557 | (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args);
558 |
559 | void (JNICALL *CallStaticVoidMethod)
560 | (JNIEnv *env, jclass cls, jmethodID methodID, ...);
561 | void (JNICALL *CallStaticVoidMethodV)
562 | (JNIEnv *env, jclass cls, jmethodID methodID, va_list args);
563 | void (JNICALL *CallStaticVoidMethodA)
564 | (JNIEnv *env, jclass cls, jmethodID methodID, const jvalue * args);
565 |
566 | jfieldID (JNICALL *GetStaticFieldID)
567 | (JNIEnv *env, jclass clazz, const char *name, const char *sig);
568 | jobject (JNICALL *GetStaticObjectField)
569 | (JNIEnv *env, jclass clazz, jfieldID fieldID);
570 | jboolean (JNICALL *GetStaticBooleanField)
571 | (JNIEnv *env, jclass clazz, jfieldID fieldID);
572 | jbyte (JNICALL *GetStaticByteField)
573 | (JNIEnv *env, jclass clazz, jfieldID fieldID);
574 | jchar (JNICALL *GetStaticCharField)
575 | (JNIEnv *env, jclass clazz, jfieldID fieldID);
576 | jshort (JNICALL *GetStaticShortField)
577 | (JNIEnv *env, jclass clazz, jfieldID fieldID);
578 | jint (JNICALL *GetStaticIntField)
579 | (JNIEnv *env, jclass clazz, jfieldID fieldID);
580 | jlong (JNICALL *GetStaticLongField)
581 | (JNIEnv *env, jclass clazz, jfieldID fieldID);
582 | jfloat (JNICALL *GetStaticFloatField)
583 | (JNIEnv *env, jclass clazz, jfieldID fieldID);
584 | jdouble (JNICALL *GetStaticDoubleField)
585 | (JNIEnv *env, jclass clazz, jfieldID fieldID);
586 |
587 | void (JNICALL *SetStaticObjectField)
588 | (JNIEnv *env, jclass clazz, jfieldID fieldID, jobject value);
589 | void (JNICALL *SetStaticBooleanField)
590 | (JNIEnv *env, jclass clazz, jfieldID fieldID, jboolean value);
591 | void (JNICALL *SetStaticByteField)
592 | (JNIEnv *env, jclass clazz, jfieldID fieldID, jbyte value);
593 | void (JNICALL *SetStaticCharField)
594 | (JNIEnv *env, jclass clazz, jfieldID fieldID, jchar value);
595 | void (JNICALL *SetStaticShortField)
596 | (JNIEnv *env, jclass clazz, jfieldID fieldID, jshort value);
597 | void (JNICALL *SetStaticIntField)
598 | (JNIEnv *env, jclass clazz, jfieldID fieldID, jint value);
599 | void (JNICALL *SetStaticLongField)
600 | (JNIEnv *env, jclass clazz, jfieldID fieldID, jlong value);
601 | void (JNICALL *SetStaticFloatField)
602 | (JNIEnv *env, jclass clazz, jfieldID fieldID, jfloat value);
603 | void (JNICALL *SetStaticDoubleField)
604 | (JNIEnv *env, jclass clazz, jfieldID fieldID, jdouble value);
605 |
606 | jstring (JNICALL *NewString)
607 | (JNIEnv *env, const jchar *unicode, jsize len);
608 | jsize (JNICALL *GetStringLength)
609 | (JNIEnv *env, jstring str);
610 | const jchar *(JNICALL *GetStringChars)
611 | (JNIEnv *env, jstring str, jboolean *isCopy);
612 | void (JNICALL *ReleaseStringChars)
613 | (JNIEnv *env, jstring str, const jchar *chars);
614 |
615 | jstring (JNICALL *NewStringUTF)
616 | (JNIEnv *env, const char *utf);
617 | jsize (JNICALL *GetStringUTFLength)
618 | (JNIEnv *env, jstring str);
619 | const char* (JNICALL *GetStringUTFChars)
620 | (JNIEnv *env, jstring str, jboolean *isCopy);
621 | void (JNICALL *ReleaseStringUTFChars)
622 | (JNIEnv *env, jstring str, const char* chars);
623 |
624 |
625 | jsize (JNICALL *GetArrayLength)
626 | (JNIEnv *env, jarray array);
627 |
628 | jobjectArray (JNICALL *NewObjectArray)
629 | (JNIEnv *env, jsize len, jclass clazz, jobject init);
630 | jobject (JNICALL *GetObjectArrayElement)
631 | (JNIEnv *env, jobjectArray array, jsize index);
632 | void (JNICALL *SetObjectArrayElement)
633 | (JNIEnv *env, jobjectArray array, jsize index, jobject val);
634 |
635 | jbooleanArray (JNICALL *NewBooleanArray)
636 | (JNIEnv *env, jsize len);
637 | jbyteArray (JNICALL *NewByteArray)
638 | (JNIEnv *env, jsize len);
639 | jcharArray (JNICALL *NewCharArray)
640 | (JNIEnv *env, jsize len);
641 | jshortArray (JNICALL *NewShortArray)
642 | (JNIEnv *env, jsize len);
643 | jintArray (JNICALL *NewIntArray)
644 | (JNIEnv *env, jsize len);
645 | jlongArray (JNICALL *NewLongArray)
646 | (JNIEnv *env, jsize len);
647 | jfloatArray (JNICALL *NewFloatArray)
648 | (JNIEnv *env, jsize len);
649 | jdoubleArray (JNICALL *NewDoubleArray)
650 | (JNIEnv *env, jsize len);
651 |
652 | jboolean * (JNICALL *GetBooleanArrayElements)
653 | (JNIEnv *env, jbooleanArray array, jboolean *isCopy);
654 | jbyte * (JNICALL *GetByteArrayElements)
655 | (JNIEnv *env, jbyteArray array, jboolean *isCopy);
656 | jchar * (JNICALL *GetCharArrayElements)
657 | (JNIEnv *env, jcharArray array, jboolean *isCopy);
658 | jshort * (JNICALL *GetShortArrayElements)
659 | (JNIEnv *env, jshortArray array, jboolean *isCopy);
660 | jint * (JNICALL *GetIntArrayElements)
661 | (JNIEnv *env, jintArray array, jboolean *isCopy);
662 | jlong * (JNICALL *GetLongArrayElements)
663 | (JNIEnv *env, jlongArray array, jboolean *isCopy);
664 | jfloat * (JNICALL *GetFloatArrayElements)
665 | (JNIEnv *env, jfloatArray array, jboolean *isCopy);
666 | jdouble * (JNICALL *GetDoubleArrayElements)
667 | (JNIEnv *env, jdoubleArray array, jboolean *isCopy);
668 |
669 | void (JNICALL *ReleaseBooleanArrayElements)
670 | (JNIEnv *env, jbooleanArray array, jboolean *elems, jint mode);
671 | void (JNICALL *ReleaseByteArrayElements)
672 | (JNIEnv *env, jbyteArray array, jbyte *elems, jint mode);
673 | void (JNICALL *ReleaseCharArrayElements)
674 | (JNIEnv *env, jcharArray array, jchar *elems, jint mode);
675 | void (JNICALL *ReleaseShortArrayElements)
676 | (JNIEnv *env, jshortArray array, jshort *elems, jint mode);
677 | void (JNICALL *ReleaseIntArrayElements)
678 | (JNIEnv *env, jintArray array, jint *elems, jint mode);
679 | void (JNICALL *ReleaseLongArrayElements)
680 | (JNIEnv *env, jlongArray array, jlong *elems, jint mode);
681 | void (JNICALL *ReleaseFloatArrayElements)
682 | (JNIEnv *env, jfloatArray array, jfloat *elems, jint mode);
683 | void (JNICALL *ReleaseDoubleArrayElements)
684 | (JNIEnv *env, jdoubleArray array, jdouble *elems, jint mode);
685 |
686 | void (JNICALL *GetBooleanArrayRegion)
687 | (JNIEnv *env, jbooleanArray array, jsize start, jsize l, jboolean *buf);
688 | void (JNICALL *GetByteArrayRegion)
689 | (JNIEnv *env, jbyteArray array, jsize start, jsize len, jbyte *buf);
690 | void (JNICALL *GetCharArrayRegion)
691 | (JNIEnv *env, jcharArray array, jsize start, jsize len, jchar *buf);
692 | void (JNICALL *GetShortArrayRegion)
693 | (JNIEnv *env, jshortArray array, jsize start, jsize len, jshort *buf);
694 | void (JNICALL *GetIntArrayRegion)
695 | (JNIEnv *env, jintArray array, jsize start, jsize len, jint *buf);
696 | void (JNICALL *GetLongArrayRegion)
697 | (JNIEnv *env, jlongArray array, jsize start, jsize len, jlong *buf);
698 | void (JNICALL *GetFloatArrayRegion)
699 | (JNIEnv *env, jfloatArray array, jsize start, jsize len, jfloat *buf);
700 | void (JNICALL *GetDoubleArrayRegion)
701 | (JNIEnv *env, jdoubleArray array, jsize start, jsize len, jdouble *buf);
702 |
703 | void (JNICALL *SetBooleanArrayRegion)
704 | (JNIEnv *env, jbooleanArray array, jsize start, jsize l, const jboolean *buf);
705 | void (JNICALL *SetByteArrayRegion)
706 | (JNIEnv *env, jbyteArray array, jsize start, jsize len, const jbyte *buf);
707 | void (JNICALL *SetCharArrayRegion)
708 | (JNIEnv *env, jcharArray array, jsize start, jsize len, const jchar *buf);
709 | void (JNICALL *SetShortArrayRegion)
710 | (JNIEnv *env, jshortArray array, jsize start, jsize len, const jshort *buf);
711 | void (JNICALL *SetIntArrayRegion)
712 | (JNIEnv *env, jintArray array, jsize start, jsize len, const jint *buf);
713 | void (JNICALL *SetLongArrayRegion)
714 | (JNIEnv *env, jlongArray array, jsize start, jsize len, const jlong *buf);
715 | void (JNICALL *SetFloatArrayRegion)
716 | (JNIEnv *env, jfloatArray array, jsize start, jsize len, const jfloat *buf);
717 | void (JNICALL *SetDoubleArrayRegion)
718 | (JNIEnv *env, jdoubleArray array, jsize start, jsize len, const jdouble *buf);
719 |
720 | jint (JNICALL *RegisterNatives)
721 | (JNIEnv *env, jclass clazz, const JNINativeMethod *methods,
722 | jint nMethods);
723 | jint (JNICALL *UnregisterNatives)
724 | (JNIEnv *env, jclass clazz);
725 |
726 | jint (JNICALL *MonitorEnter)
727 | (JNIEnv *env, jobject obj);
728 | jint (JNICALL *MonitorExit)
729 | (JNIEnv *env, jobject obj);
730 |
731 | jint (JNICALL *GetJavaVM)
732 | (JNIEnv *env, JavaVM **vm);
733 |
734 | void (JNICALL *GetStringRegion)
735 | (JNIEnv *env, jstring str, jsize start, jsize len, jchar *buf);
736 | void (JNICALL *GetStringUTFRegion)
737 | (JNIEnv *env, jstring str, jsize start, jsize len, char *buf);
738 |
739 | void * (JNICALL *GetPrimitiveArrayCritical)
740 | (JNIEnv *env, jarray array, jboolean *isCopy);
741 | void (JNICALL *ReleasePrimitiveArrayCritical)
742 | (JNIEnv *env, jarray array, void *carray, jint mode);
743 |
744 | const jchar * (JNICALL *GetStringCritical)
745 | (JNIEnv *env, jstring string, jboolean *isCopy);
746 | void (JNICALL *ReleaseStringCritical)
747 | (JNIEnv *env, jstring string, const jchar *cstring);
748 |
749 | jweak (JNICALL *NewWeakGlobalRef)
750 | (JNIEnv *env, jobject obj);
751 | void (JNICALL *DeleteWeakGlobalRef)
752 | (JNIEnv *env, jweak ref);
753 |
754 | jboolean (JNICALL *ExceptionCheck)
755 | (JNIEnv *env);
756 |
757 | jobject (JNICALL *NewDirectByteBuffer)
758 | (JNIEnv* env, void* address, jlong capacity);
759 | void* (JNICALL *GetDirectBufferAddress)
760 | (JNIEnv* env, jobject buf);
761 | jlong (JNICALL *GetDirectBufferCapacity)
762 | (JNIEnv* env, jobject buf);
763 |
764 | /* New JNI 1.6 Features */
765 |
766 | jobjectRefType (JNICALL *GetObjectRefType)
767 | (JNIEnv* env, jobject obj);
768 | };
769 |
770 | /*
771 | * We use inlined functions for C++ so that programmers can write:
772 | *
773 | * env->FindClass("java/lang/String")
774 | *
775 | * in C++ rather than:
776 | *
777 | * (*env)->FindClass(env, "java/lang/String")
778 | *
779 | * in C.
780 | */
781 |
782 | struct JNIEnv_ {
783 | const struct JNINativeInterface_ *functions;
784 | #ifdef __cplusplus
785 |
786 | jint GetVersion() {
787 | return functions->GetVersion(this);
788 | }
789 | jclass DefineClass(const char *name, jobject loader, const jbyte *buf,
790 | jsize len) {
791 | return functions->DefineClass(this, name, loader, buf, len);
792 | }
793 | jclass FindClass(const char *name) {
794 | return functions->FindClass(this, name);
795 | }
796 | jmethodID FromReflectedMethod(jobject method) {
797 | return functions->FromReflectedMethod(this,method);
798 | }
799 | jfieldID FromReflectedField(jobject field) {
800 | return functions->FromReflectedField(this,field);
801 | }
802 |
803 | jobject ToReflectedMethod(jclass cls, jmethodID methodID, jboolean isStatic) {
804 | return functions->ToReflectedMethod(this, cls, methodID, isStatic);
805 | }
806 |
807 | jclass GetSuperclass(jclass sub) {
808 | return functions->GetSuperclass(this, sub);
809 | }
810 | jboolean IsAssignableFrom(jclass sub, jclass sup) {
811 | return functions->IsAssignableFrom(this, sub, sup);
812 | }
813 |
814 | jobject ToReflectedField(jclass cls, jfieldID fieldID, jboolean isStatic) {
815 | return functions->ToReflectedField(this,cls,fieldID,isStatic);
816 | }
817 |
818 | jint Throw(jthrowable obj) {
819 | return functions->Throw(this, obj);
820 | }
821 | jint ThrowNew(jclass clazz, const char *msg) {
822 | return functions->ThrowNew(this, clazz, msg);
823 | }
824 | jthrowable ExceptionOccurred() {
825 | return functions->ExceptionOccurred(this);
826 | }
827 | void ExceptionDescribe() {
828 | functions->ExceptionDescribe(this);
829 | }
830 | void ExceptionClear() {
831 | functions->ExceptionClear(this);
832 | }
833 | void FatalError(const char *msg) {
834 | functions->FatalError(this, msg);
835 | }
836 |
837 | jint PushLocalFrame(jint capacity) {
838 | return functions->PushLocalFrame(this,capacity);
839 | }
840 | jobject PopLocalFrame(jobject result) {
841 | return functions->PopLocalFrame(this,result);
842 | }
843 |
844 | jobject NewGlobalRef(jobject lobj) {
845 | return functions->NewGlobalRef(this,lobj);
846 | }
847 | void DeleteGlobalRef(jobject gref) {
848 | functions->DeleteGlobalRef(this,gref);
849 | }
850 | void DeleteLocalRef(jobject obj) {
851 | functions->DeleteLocalRef(this, obj);
852 | }
853 |
854 | jboolean IsSameObject(jobject obj1, jobject obj2) {
855 | return functions->IsSameObject(this,obj1,obj2);
856 | }
857 |
858 | jobject NewLocalRef(jobject ref) {
859 | return functions->NewLocalRef(this,ref);
860 | }
861 | jint EnsureLocalCapacity(jint capacity) {
862 | return functions->EnsureLocalCapacity(this,capacity);
863 | }
864 |
865 | jobject AllocObject(jclass clazz) {
866 | return functions->AllocObject(this,clazz);
867 | }
868 | jobject NewObject(jclass clazz, jmethodID methodID, ...) {
869 | va_list args;
870 | jobject result;
871 | va_start(args, methodID);
872 | result = functions->NewObjectV(this,clazz,methodID,args);
873 | va_end(args);
874 | return result;
875 | }
876 | jobject NewObjectV(jclass clazz, jmethodID methodID,
877 | va_list args) {
878 | return functions->NewObjectV(this,clazz,methodID,args);
879 | }
880 | jobject NewObjectA(jclass clazz, jmethodID methodID,
881 | const jvalue *args) {
882 | return functions->NewObjectA(this,clazz,methodID,args);
883 | }
884 |
885 | jclass GetObjectClass(jobject obj) {
886 | return functions->GetObjectClass(this,obj);
887 | }
888 | jboolean IsInstanceOf(jobject obj, jclass clazz) {
889 | return functions->IsInstanceOf(this,obj,clazz);
890 | }
891 |
892 | jmethodID GetMethodID(jclass clazz, const char *name,
893 | const char *sig) {
894 | return functions->GetMethodID(this,clazz,name,sig);
895 | }
896 |
897 | jobject CallObjectMethod(jobject obj, jmethodID methodID, ...) {
898 | va_list args;
899 | jobject result;
900 | va_start(args,methodID);
901 | result = functions->CallObjectMethodV(this,obj,methodID,args);
902 | va_end(args);
903 | return result;
904 | }
905 | jobject CallObjectMethodV(jobject obj, jmethodID methodID,
906 | va_list args) {
907 | return functions->CallObjectMethodV(this,obj,methodID,args);
908 | }
909 | jobject CallObjectMethodA(jobject obj, jmethodID methodID,
910 | const jvalue * args) {
911 | return functions->CallObjectMethodA(this,obj,methodID,args);
912 | }
913 |
914 | jboolean CallBooleanMethod(jobject obj,
915 | jmethodID methodID, ...) {
916 | va_list args;
917 | jboolean result;
918 | va_start(args,methodID);
919 | result = functions->CallBooleanMethodV(this,obj,methodID,args);
920 | va_end(args);
921 | return result;
922 | }
923 | jboolean CallBooleanMethodV(jobject obj, jmethodID methodID,
924 | va_list args) {
925 | return functions->CallBooleanMethodV(this,obj,methodID,args);
926 | }
927 | jboolean CallBooleanMethodA(jobject obj, jmethodID methodID,
928 | const jvalue * args) {
929 | return functions->CallBooleanMethodA(this,obj,methodID, args);
930 | }
931 |
932 | jbyte CallByteMethod(jobject obj, jmethodID methodID, ...) {
933 | va_list args;
934 | jbyte result;
935 | va_start(args,methodID);
936 | result = functions->CallByteMethodV(this,obj,methodID,args);
937 | va_end(args);
938 | return result;
939 | }
940 | jbyte CallByteMethodV(jobject obj, jmethodID methodID,
941 | va_list args) {
942 | return functions->CallByteMethodV(this,obj,methodID,args);
943 | }
944 | jbyte CallByteMethodA(jobject obj, jmethodID methodID,
945 | const jvalue * args) {
946 | return functions->CallByteMethodA(this,obj,methodID,args);
947 | }
948 |
949 | jchar CallCharMethod(jobject obj, jmethodID methodID, ...) {
950 | va_list args;
951 | jchar result;
952 | va_start(args,methodID);
953 | result = functions->CallCharMethodV(this,obj,methodID,args);
954 | va_end(args);
955 | return result;
956 | }
957 | jchar CallCharMethodV(jobject obj, jmethodID methodID,
958 | va_list args) {
959 | return functions->CallCharMethodV(this,obj,methodID,args);
960 | }
961 | jchar CallCharMethodA(jobject obj, jmethodID methodID,
962 | const jvalue * args) {
963 | return functions->CallCharMethodA(this,obj,methodID,args);
964 | }
965 |
966 | jshort CallShortMethod(jobject obj, jmethodID methodID, ...) {
967 | va_list args;
968 | jshort result;
969 | va_start(args,methodID);
970 | result = functions->CallShortMethodV(this,obj,methodID,args);
971 | va_end(args);
972 | return result;
973 | }
974 | jshort CallShortMethodV(jobject obj, jmethodID methodID,
975 | va_list args) {
976 | return functions->CallShortMethodV(this,obj,methodID,args);
977 | }
978 | jshort CallShortMethodA(jobject obj, jmethodID methodID,
979 | const jvalue * args) {
980 | return functions->CallShortMethodA(this,obj,methodID,args);
981 | }
982 |
983 | jint CallIntMethod(jobject obj, jmethodID methodID, ...) {
984 | va_list args;
985 | jint result;
986 | va_start(args,methodID);
987 | result = functions->CallIntMethodV(this,obj,methodID,args);
988 | va_end(args);
989 | return result;
990 | }
991 | jint CallIntMethodV(jobject obj, jmethodID methodID,
992 | va_list args) {
993 | return functions->CallIntMethodV(this,obj,methodID,args);
994 | }
995 | jint CallIntMethodA(jobject obj, jmethodID methodID,
996 | const jvalue * args) {
997 | return functions->CallIntMethodA(this,obj,methodID,args);
998 | }
999 |
1000 | jlong CallLongMethod(jobject obj, jmethodID methodID, ...) {
1001 | va_list args;
1002 | jlong result;
1003 | va_start(args,methodID);
1004 | result = functions->CallLongMethodV(this,obj,methodID,args);
1005 | va_end(args);
1006 | return result;
1007 | }
1008 | jlong CallLongMethodV(jobject obj, jmethodID methodID,
1009 | va_list args) {
1010 | return functions->CallLongMethodV(this,obj,methodID,args);
1011 | }
1012 | jlong CallLongMethodA(jobject obj, jmethodID methodID,
1013 | const jvalue * args) {
1014 | return functions->CallLongMethodA(this,obj,methodID,args);
1015 | }
1016 |
1017 | jfloat CallFloatMethod(jobject obj, jmethodID methodID, ...) {
1018 | va_list args;
1019 | jfloat result;
1020 | va_start(args,methodID);
1021 | result = functions->CallFloatMethodV(this,obj,methodID,args);
1022 | va_end(args);
1023 | return result;
1024 | }
1025 | jfloat CallFloatMethodV(jobject obj, jmethodID methodID,
1026 | va_list args) {
1027 | return functions->CallFloatMethodV(this,obj,methodID,args);
1028 | }
1029 | jfloat CallFloatMethodA(jobject obj, jmethodID methodID,
1030 | const jvalue * args) {
1031 | return functions->CallFloatMethodA(this,obj,methodID,args);
1032 | }
1033 |
1034 | jdouble CallDoubleMethod(jobject obj, jmethodID methodID, ...) {
1035 | va_list args;
1036 | jdouble result;
1037 | va_start(args,methodID);
1038 | result = functions->CallDoubleMethodV(this,obj,methodID,args);
1039 | va_end(args);
1040 | return result;
1041 | }
1042 | jdouble CallDoubleMethodV(jobject obj, jmethodID methodID,
1043 | va_list args) {
1044 | return functions->CallDoubleMethodV(this,obj,methodID,args);
1045 | }
1046 | jdouble CallDoubleMethodA(jobject obj, jmethodID methodID,
1047 | const jvalue * args) {
1048 | return functions->CallDoubleMethodA(this,obj,methodID,args);
1049 | }
1050 |
1051 | void CallVoidMethod(jobject obj, jmethodID methodID, ...) {
1052 | va_list args;
1053 | va_start(args,methodID);
1054 | functions->CallVoidMethodV(this,obj,methodID,args);
1055 | va_end(args);
1056 | }
1057 | void CallVoidMethodV(jobject obj, jmethodID methodID,
1058 | va_list args) {
1059 | functions->CallVoidMethodV(this,obj,methodID,args);
1060 | }
1061 | void CallVoidMethodA(jobject obj, jmethodID methodID,
1062 | const jvalue * args) {
1063 | functions->CallVoidMethodA(this,obj,methodID,args);
1064 | }
1065 |
1066 | jobject CallNonvirtualObjectMethod(jobject obj, jclass clazz,
1067 | jmethodID methodID, ...) {
1068 | va_list args;
1069 | jobject result;
1070 | va_start(args,methodID);
1071 | result = functions->CallNonvirtualObjectMethodV(this,obj,clazz,
1072 | methodID,args);
1073 | va_end(args);
1074 | return result;
1075 | }
1076 | jobject CallNonvirtualObjectMethodV(jobject obj, jclass clazz,
1077 | jmethodID methodID, va_list args) {
1078 | return functions->CallNonvirtualObjectMethodV(this,obj,clazz,
1079 | methodID,args);
1080 | }
1081 | jobject CallNonvirtualObjectMethodA(jobject obj, jclass clazz,
1082 | jmethodID methodID, const jvalue * args) {
1083 | return functions->CallNonvirtualObjectMethodA(this,obj,clazz,
1084 | methodID,args);
1085 | }
1086 |
1087 | jboolean CallNonvirtualBooleanMethod(jobject obj, jclass clazz,
1088 | jmethodID methodID, ...) {
1089 | va_list args;
1090 | jboolean result;
1091 | va_start(args,methodID);
1092 | result = functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
1093 | methodID,args);
1094 | va_end(args);
1095 | return result;
1096 | }
1097 | jboolean CallNonvirtualBooleanMethodV(jobject obj, jclass clazz,
1098 | jmethodID methodID, va_list args) {
1099 | return functions->CallNonvirtualBooleanMethodV(this,obj,clazz,
1100 | methodID,args);
1101 | }
1102 | jboolean CallNonvirtualBooleanMethodA(jobject obj, jclass clazz,
1103 | jmethodID methodID, const jvalue * args) {
1104 | return functions->CallNonvirtualBooleanMethodA(this,obj,clazz,
1105 | methodID, args);
1106 | }
1107 |
1108 | jbyte CallNonvirtualByteMethod(jobject obj, jclass clazz,
1109 | jmethodID methodID, ...) {
1110 | va_list args;
1111 | jbyte result;
1112 | va_start(args,methodID);
1113 | result = functions->CallNonvirtualByteMethodV(this,obj,clazz,
1114 | methodID,args);
1115 | va_end(args);
1116 | return result;
1117 | }
1118 | jbyte CallNonvirtualByteMethodV(jobject obj, jclass clazz,
1119 | jmethodID methodID, va_list args) {
1120 | return functions->CallNonvirtualByteMethodV(this,obj,clazz,
1121 | methodID,args);
1122 | }
1123 | jbyte CallNonvirtualByteMethodA(jobject obj, jclass clazz,
1124 | jmethodID methodID, const jvalue * args) {
1125 | return functions->CallNonvirtualByteMethodA(this,obj,clazz,
1126 | methodID,args);
1127 | }
1128 |
1129 | jchar CallNonvirtualCharMethod(jobject obj, jclass clazz,
1130 | jmethodID methodID, ...) {
1131 | va_list args;
1132 | jchar result;
1133 | va_start(args,methodID);
1134 | result = functions->CallNonvirtualCharMethodV(this,obj,clazz,
1135 | methodID,args);
1136 | va_end(args);
1137 | return result;
1138 | }
1139 | jchar CallNonvirtualCharMethodV(jobject obj, jclass clazz,
1140 | jmethodID methodID, va_list args) {
1141 | return functions->CallNonvirtualCharMethodV(this,obj,clazz,
1142 | methodID,args);
1143 | }
1144 | jchar CallNonvirtualCharMethodA(jobject obj, jclass clazz,
1145 | jmethodID methodID, const jvalue * args) {
1146 | return functions->CallNonvirtualCharMethodA(this,obj,clazz,
1147 | methodID,args);
1148 | }
1149 |
1150 | jshort CallNonvirtualShortMethod(jobject obj, jclass clazz,
1151 | jmethodID methodID, ...) {
1152 | va_list args;
1153 | jshort result;
1154 | va_start(args,methodID);
1155 | result = functions->CallNonvirtualShortMethodV(this,obj,clazz,
1156 | methodID,args);
1157 | va_end(args);
1158 | return result;
1159 | }
1160 | jshort CallNonvirtualShortMethodV(jobject obj, jclass clazz,
1161 | jmethodID methodID, va_list args) {
1162 | return functions->CallNonvirtualShortMethodV(this,obj,clazz,
1163 | methodID,args);
1164 | }
1165 | jshort CallNonvirtualShortMethodA(jobject obj, jclass clazz,
1166 | jmethodID methodID, const jvalue * args) {
1167 | return functions->CallNonvirtualShortMethodA(this,obj,clazz,
1168 | methodID,args);
1169 | }
1170 |
1171 | jint CallNonvirtualIntMethod(jobject obj, jclass clazz,
1172 | jmethodID methodID, ...) {
1173 | va_list args;
1174 | jint result;
1175 | va_start(args,methodID);
1176 | result = functions->CallNonvirtualIntMethodV(this,obj,clazz,
1177 | methodID,args);
1178 | va_end(args);
1179 | return result;
1180 | }
1181 | jint CallNonvirtualIntMethodV(jobject obj, jclass clazz,
1182 | jmethodID methodID, va_list args) {
1183 | return functions->CallNonvirtualIntMethodV(this,obj,clazz,
1184 | methodID,args);
1185 | }
1186 | jint CallNonvirtualIntMethodA(jobject obj, jclass clazz,
1187 | jmethodID methodID, const jvalue * args) {
1188 | return functions->CallNonvirtualIntMethodA(this,obj,clazz,
1189 | methodID,args);
1190 | }
1191 |
1192 | jlong CallNonvirtualLongMethod(jobject obj, jclass clazz,
1193 | jmethodID methodID, ...) {
1194 | va_list args;
1195 | jlong result;
1196 | va_start(args,methodID);
1197 | result = functions->CallNonvirtualLongMethodV(this,obj,clazz,
1198 | methodID,args);
1199 | va_end(args);
1200 | return result;
1201 | }
1202 | jlong CallNonvirtualLongMethodV(jobject obj, jclass clazz,
1203 | jmethodID methodID, va_list args) {
1204 | return functions->CallNonvirtualLongMethodV(this,obj,clazz,
1205 | methodID,args);
1206 | }
1207 | jlong CallNonvirtualLongMethodA(jobject obj, jclass clazz,
1208 | jmethodID methodID, const jvalue * args) {
1209 | return functions->CallNonvirtualLongMethodA(this,obj,clazz,
1210 | methodID,args);
1211 | }
1212 |
1213 | jfloat CallNonvirtualFloatMethod(jobject obj, jclass clazz,
1214 | jmethodID methodID, ...) {
1215 | va_list args;
1216 | jfloat result;
1217 | va_start(args,methodID);
1218 | result = functions->CallNonvirtualFloatMethodV(this,obj,clazz,
1219 | methodID,args);
1220 | va_end(args);
1221 | return result;
1222 | }
1223 | jfloat CallNonvirtualFloatMethodV(jobject obj, jclass clazz,
1224 | jmethodID methodID,
1225 | va_list args) {
1226 | return functions->CallNonvirtualFloatMethodV(this,obj,clazz,
1227 | methodID,args);
1228 | }
1229 | jfloat CallNonvirtualFloatMethodA(jobject obj, jclass clazz,
1230 | jmethodID methodID,
1231 | const jvalue * args) {
1232 | return functions->CallNonvirtualFloatMethodA(this,obj,clazz,
1233 | methodID,args);
1234 | }
1235 |
1236 | jdouble CallNonvirtualDoubleMethod(jobject obj, jclass clazz,
1237 | jmethodID methodID, ...) {
1238 | va_list args;
1239 | jdouble result;
1240 | va_start(args,methodID);
1241 | result = functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
1242 | methodID,args);
1243 | va_end(args);
1244 | return result;
1245 | }
1246 | jdouble CallNonvirtualDoubleMethodV(jobject obj, jclass clazz,
1247 | jmethodID methodID,
1248 | va_list args) {
1249 | return functions->CallNonvirtualDoubleMethodV(this,obj,clazz,
1250 | methodID,args);
1251 | }
1252 | jdouble CallNonvirtualDoubleMethodA(jobject obj, jclass clazz,
1253 | jmethodID methodID,
1254 | const jvalue * args) {
1255 | return functions->CallNonvirtualDoubleMethodA(this,obj,clazz,
1256 | methodID,args);
1257 | }
1258 |
1259 | void CallNonvirtualVoidMethod(jobject obj, jclass clazz,
1260 | jmethodID methodID, ...) {
1261 | va_list args;
1262 | va_start(args,methodID);
1263 | functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
1264 | va_end(args);
1265 | }
1266 | void CallNonvirtualVoidMethodV(jobject obj, jclass clazz,
1267 | jmethodID methodID,
1268 | va_list args) {
1269 | functions->CallNonvirtualVoidMethodV(this,obj,clazz,methodID,args);
1270 | }
1271 | void CallNonvirtualVoidMethodA(jobject obj, jclass clazz,
1272 | jmethodID methodID,
1273 | const jvalue * args) {
1274 | functions->CallNonvirtualVoidMethodA(this,obj,clazz,methodID,args);
1275 | }
1276 |
1277 | jfieldID GetFieldID(jclass clazz, const char *name,
1278 | const char *sig) {
1279 | return functions->GetFieldID(this,clazz,name,sig);
1280 | }
1281 |
1282 | jobject GetObjectField(jobject obj, jfieldID fieldID) {
1283 | return functions->GetObjectField(this,obj,fieldID);
1284 | }
1285 | jboolean GetBooleanField(jobject obj, jfieldID fieldID) {
1286 | return functions->GetBooleanField(this,obj,fieldID);
1287 | }
1288 | jbyte GetByteField(jobject obj, jfieldID fieldID) {
1289 | return functions->GetByteField(this,obj,fieldID);
1290 | }
1291 | jchar GetCharField(jobject obj, jfieldID fieldID) {
1292 | return functions->GetCharField(this,obj,fieldID);
1293 | }
1294 | jshort GetShortField(jobject obj, jfieldID fieldID) {
1295 | return functions->GetShortField(this,obj,fieldID);
1296 | }
1297 | jint GetIntField(jobject obj, jfieldID fieldID) {
1298 | return functions->GetIntField(this,obj,fieldID);
1299 | }
1300 | jlong GetLongField(jobject obj, jfieldID fieldID) {
1301 | return functions->GetLongField(this,obj,fieldID);
1302 | }
1303 | jfloat GetFloatField(jobject obj, jfieldID fieldID) {
1304 | return functions->GetFloatField(this,obj,fieldID);
1305 | }
1306 | jdouble GetDoubleField(jobject obj, jfieldID fieldID) {
1307 | return functions->GetDoubleField(this,obj,fieldID);
1308 | }
1309 |
1310 | void SetObjectField(jobject obj, jfieldID fieldID, jobject val) {
1311 | functions->SetObjectField(this,obj,fieldID,val);
1312 | }
1313 | void SetBooleanField(jobject obj, jfieldID fieldID,
1314 | jboolean val) {
1315 | functions->SetBooleanField(this,obj,fieldID,val);
1316 | }
1317 | void SetByteField(jobject obj, jfieldID fieldID,
1318 | jbyte val) {
1319 | functions->SetByteField(this,obj,fieldID,val);
1320 | }
1321 | void SetCharField(jobject obj, jfieldID fieldID,
1322 | jchar val) {
1323 | functions->SetCharField(this,obj,fieldID,val);
1324 | }
1325 | void SetShortField(jobject obj, jfieldID fieldID,
1326 | jshort val) {
1327 | functions->SetShortField(this,obj,fieldID,val);
1328 | }
1329 | void SetIntField(jobject obj, jfieldID fieldID,
1330 | jint val) {
1331 | functions->SetIntField(this,obj,fieldID,val);
1332 | }
1333 | void SetLongField(jobject obj, jfieldID fieldID,
1334 | jlong val) {
1335 | functions->SetLongField(this,obj,fieldID,val);
1336 | }
1337 | void SetFloatField(jobject obj, jfieldID fieldID,
1338 | jfloat val) {
1339 | functions->SetFloatField(this,obj,fieldID,val);
1340 | }
1341 | void SetDoubleField(jobject obj, jfieldID fieldID,
1342 | jdouble val) {
1343 | functions->SetDoubleField(this,obj,fieldID,val);
1344 | }
1345 |
1346 | jmethodID GetStaticMethodID(jclass clazz, const char *name,
1347 | const char *sig) {
1348 | return functions->GetStaticMethodID(this,clazz,name,sig);
1349 | }
1350 |
1351 | jobject CallStaticObjectMethod(jclass clazz, jmethodID methodID,
1352 | ...) {
1353 | va_list args;
1354 | jobject result;
1355 | va_start(args,methodID);
1356 | result = functions->CallStaticObjectMethodV(this,clazz,methodID,args);
1357 | va_end(args);
1358 | return result;
1359 | }
1360 | jobject CallStaticObjectMethodV(jclass clazz, jmethodID methodID,
1361 | va_list args) {
1362 | return functions->CallStaticObjectMethodV(this,clazz,methodID,args);
1363 | }
1364 | jobject CallStaticObjectMethodA(jclass clazz, jmethodID methodID,
1365 | const jvalue *args) {
1366 | return functions->CallStaticObjectMethodA(this,clazz,methodID,args);
1367 | }
1368 |
1369 | jboolean CallStaticBooleanMethod(jclass clazz,
1370 | jmethodID methodID, ...) {
1371 | va_list args;
1372 | jboolean result;
1373 | va_start(args,methodID);
1374 | result = functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
1375 | va_end(args);
1376 | return result;
1377 | }
1378 | jboolean CallStaticBooleanMethodV(jclass clazz,
1379 | jmethodID methodID, va_list args) {
1380 | return functions->CallStaticBooleanMethodV(this,clazz,methodID,args);
1381 | }
1382 | jboolean CallStaticBooleanMethodA(jclass clazz,
1383 | jmethodID methodID, const jvalue *args) {
1384 | return functions->CallStaticBooleanMethodA(this,clazz,methodID,args);
1385 | }
1386 |
1387 | jbyte CallStaticByteMethod(jclass clazz,
1388 | jmethodID methodID, ...) {
1389 | va_list args;
1390 | jbyte result;
1391 | va_start(args,methodID);
1392 | result = functions->CallStaticByteMethodV(this,clazz,methodID,args);
1393 | va_end(args);
1394 | return result;
1395 | }
1396 | jbyte CallStaticByteMethodV(jclass clazz,
1397 | jmethodID methodID, va_list args) {
1398 | return functions->CallStaticByteMethodV(this,clazz,methodID,args);
1399 | }
1400 | jbyte CallStaticByteMethodA(jclass clazz,
1401 | jmethodID methodID, const jvalue *args) {
1402 | return functions->CallStaticByteMethodA(this,clazz,methodID,args);
1403 | }
1404 |
1405 | jchar CallStaticCharMethod(jclass clazz,
1406 | jmethodID methodID, ...) {
1407 | va_list args;
1408 | jchar result;
1409 | va_start(args,methodID);
1410 | result = functions->CallStaticCharMethodV(this,clazz,methodID,args);
1411 | va_end(args);
1412 | return result;
1413 | }
1414 | jchar CallStaticCharMethodV(jclass clazz,
1415 | jmethodID methodID, va_list args) {
1416 | return functions->CallStaticCharMethodV(this,clazz,methodID,args);
1417 | }
1418 | jchar CallStaticCharMethodA(jclass clazz,
1419 | jmethodID methodID, const jvalue *args) {
1420 | return functions->CallStaticCharMethodA(this,clazz,methodID,args);
1421 | }
1422 |
1423 | jshort CallStaticShortMethod(jclass clazz,
1424 | jmethodID methodID, ...) {
1425 | va_list args;
1426 | jshort result;
1427 | va_start(args,methodID);
1428 | result = functions->CallStaticShortMethodV(this,clazz,methodID,args);
1429 | va_end(args);
1430 | return result;
1431 | }
1432 | jshort CallStaticShortMethodV(jclass clazz,
1433 | jmethodID methodID, va_list args) {
1434 | return functions->CallStaticShortMethodV(this,clazz,methodID,args);
1435 | }
1436 | jshort CallStaticShortMethodA(jclass clazz,
1437 | jmethodID methodID, const jvalue *args) {
1438 | return functions->CallStaticShortMethodA(this,clazz,methodID,args);
1439 | }
1440 |
1441 | jint CallStaticIntMethod(jclass clazz,
1442 | jmethodID methodID, ...) {
1443 | va_list args;
1444 | jint result;
1445 | va_start(args,methodID);
1446 | result = functions->CallStaticIntMethodV(this,clazz,methodID,args);
1447 | va_end(args);
1448 | return result;
1449 | }
1450 | jint CallStaticIntMethodV(jclass clazz,
1451 | jmethodID methodID, va_list args) {
1452 | return functions->CallStaticIntMethodV(this,clazz,methodID,args);
1453 | }
1454 | jint CallStaticIntMethodA(jclass clazz,
1455 | jmethodID methodID, const jvalue *args) {
1456 | return functions->CallStaticIntMethodA(this,clazz,methodID,args);
1457 | }
1458 |
1459 | jlong CallStaticLongMethod(jclass clazz,
1460 | jmethodID methodID, ...) {
1461 | va_list args;
1462 | jlong result;
1463 | va_start(args,methodID);
1464 | result = functions->CallStaticLongMethodV(this,clazz,methodID,args);
1465 | va_end(args);
1466 | return result;
1467 | }
1468 | jlong CallStaticLongMethodV(jclass clazz,
1469 | jmethodID methodID, va_list args) {
1470 | return functions->CallStaticLongMethodV(this,clazz,methodID,args);
1471 | }
1472 | jlong CallStaticLongMethodA(jclass clazz,
1473 | jmethodID methodID, const jvalue *args) {
1474 | return functions->CallStaticLongMethodA(this,clazz,methodID,args);
1475 | }
1476 |
1477 | jfloat CallStaticFloatMethod(jclass clazz,
1478 | jmethodID methodID, ...) {
1479 | va_list args;
1480 | jfloat result;
1481 | va_start(args,methodID);
1482 | result = functions->CallStaticFloatMethodV(this,clazz,methodID,args);
1483 | va_end(args);
1484 | return result;
1485 | }
1486 | jfloat CallStaticFloatMethodV(jclass clazz,
1487 | jmethodID methodID, va_list args) {
1488 | return functions->CallStaticFloatMethodV(this,clazz,methodID,args);
1489 | }
1490 | jfloat CallStaticFloatMethodA(jclass clazz,
1491 | jmethodID methodID, const jvalue *args) {
1492 | return functions->CallStaticFloatMethodA(this,clazz,methodID,args);
1493 | }
1494 |
1495 | jdouble CallStaticDoubleMethod(jclass clazz,
1496 | jmethodID methodID, ...) {
1497 | va_list args;
1498 | jdouble result;
1499 | va_start(args,methodID);
1500 | result = functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
1501 | va_end(args);
1502 | return result;
1503 | }
1504 | jdouble CallStaticDoubleMethodV(jclass clazz,
1505 | jmethodID methodID, va_list args) {
1506 | return functions->CallStaticDoubleMethodV(this,clazz,methodID,args);
1507 | }
1508 | jdouble CallStaticDoubleMethodA(jclass clazz,
1509 | jmethodID methodID, const jvalue *args) {
1510 | return functions->CallStaticDoubleMethodA(this,clazz,methodID,args);
1511 | }
1512 |
1513 | void CallStaticVoidMethod(jclass cls, jmethodID methodID, ...) {
1514 | va_list args;
1515 | va_start(args,methodID);
1516 | functions->CallStaticVoidMethodV(this,cls,methodID,args);
1517 | va_end(args);
1518 | }
1519 | void CallStaticVoidMethodV(jclass cls, jmethodID methodID,
1520 | va_list args) {
1521 | functions->CallStaticVoidMethodV(this,cls,methodID,args);
1522 | }
1523 | void CallStaticVoidMethodA(jclass cls, jmethodID methodID,
1524 | const jvalue * args) {
1525 | functions->CallStaticVoidMethodA(this,cls,methodID,args);
1526 | }
1527 |
1528 | jfieldID GetStaticFieldID(jclass clazz, const char *name,
1529 | const char *sig) {
1530 | return functions->GetStaticFieldID(this,clazz,name,sig);
1531 | }
1532 | jobject GetStaticObjectField(jclass clazz, jfieldID fieldID) {
1533 | return functions->GetStaticObjectField(this,clazz,fieldID);
1534 | }
1535 | jboolean GetStaticBooleanField(jclass clazz, jfieldID fieldID) {
1536 | return functions->GetStaticBooleanField(this,clazz,fieldID);
1537 | }
1538 | jbyte GetStaticByteField(jclass clazz, jfieldID fieldID) {
1539 | return functions->GetStaticByteField(this,clazz,fieldID);
1540 | }
1541 | jchar GetStaticCharField(jclass clazz, jfieldID fieldID) {
1542 | return functions->GetStaticCharField(this,clazz,fieldID);
1543 | }
1544 | jshort GetStaticShortField(jclass clazz, jfieldID fieldID) {
1545 | return functions->GetStaticShortField(this,clazz,fieldID);
1546 | }
1547 | jint GetStaticIntField(jclass clazz, jfieldID fieldID) {
1548 | return functions->GetStaticIntField(this,clazz,fieldID);
1549 | }
1550 | jlong GetStaticLongField(jclass clazz, jfieldID fieldID) {
1551 | return functions->GetStaticLongField(this,clazz,fieldID);
1552 | }
1553 | jfloat GetStaticFloatField(jclass clazz, jfieldID fieldID) {
1554 | return functions->GetStaticFloatField(this,clazz,fieldID);
1555 | }
1556 | jdouble GetStaticDoubleField(jclass clazz, jfieldID fieldID) {
1557 | return functions->GetStaticDoubleField(this,clazz,fieldID);
1558 | }
1559 |
1560 | void SetStaticObjectField(jclass clazz, jfieldID fieldID,
1561 | jobject value) {
1562 | functions->SetStaticObjectField(this,clazz,fieldID,value);
1563 | }
1564 | void SetStaticBooleanField(jclass clazz, jfieldID fieldID,
1565 | jboolean value) {
1566 | functions->SetStaticBooleanField(this,clazz,fieldID,value);
1567 | }
1568 | void SetStaticByteField(jclass clazz, jfieldID fieldID,
1569 | jbyte value) {
1570 | functions->SetStaticByteField(this,clazz,fieldID,value);
1571 | }
1572 | void SetStaticCharField(jclass clazz, jfieldID fieldID,
1573 | jchar value) {
1574 | functions->SetStaticCharField(this,clazz,fieldID,value);
1575 | }
1576 | void SetStaticShortField(jclass clazz, jfieldID fieldID,
1577 | jshort value) {
1578 | functions->SetStaticShortField(this,clazz,fieldID,value);
1579 | }
1580 | void SetStaticIntField(jclass clazz, jfieldID fieldID,
1581 | jint value) {
1582 | functions->SetStaticIntField(this,clazz,fieldID,value);
1583 | }
1584 | void SetStaticLongField(jclass clazz, jfieldID fieldID,
1585 | jlong value) {
1586 | functions->SetStaticLongField(this,clazz,fieldID,value);
1587 | }
1588 | void SetStaticFloatField(jclass clazz, jfieldID fieldID,
1589 | jfloat value) {
1590 | functions->SetStaticFloatField(this,clazz,fieldID,value);
1591 | }
1592 | void SetStaticDoubleField(jclass clazz, jfieldID fieldID,
1593 | jdouble value) {
1594 | functions->SetStaticDoubleField(this,clazz,fieldID,value);
1595 | }
1596 |
1597 | jstring NewString(const jchar *unicode, jsize len) {
1598 | return functions->NewString(this,unicode,len);
1599 | }
1600 | jsize GetStringLength(jstring str) {
1601 | return functions->GetStringLength(this,str);
1602 | }
1603 | const jchar *GetStringChars(jstring str, jboolean *isCopy) {
1604 | return functions->GetStringChars(this,str,isCopy);
1605 | }
1606 | void ReleaseStringChars(jstring str, const jchar *chars) {
1607 | functions->ReleaseStringChars(this,str,chars);
1608 | }
1609 |
1610 | jstring NewStringUTF(const char *utf) {
1611 | return functions->NewStringUTF(this,utf);
1612 | }
1613 | jsize GetStringUTFLength(jstring str) {
1614 | return functions->GetStringUTFLength(this,str);
1615 | }
1616 | const char* GetStringUTFChars(jstring str, jboolean *isCopy) {
1617 | return functions->GetStringUTFChars(this,str,isCopy);
1618 | }
1619 | void ReleaseStringUTFChars(jstring str, const char* chars) {
1620 | functions->ReleaseStringUTFChars(this,str,chars);
1621 | }
1622 |
1623 | jsize GetArrayLength(jarray array) {
1624 | return functions->GetArrayLength(this,array);
1625 | }
1626 |
1627 | jobjectArray NewObjectArray(jsize len, jclass clazz,
1628 | jobject init) {
1629 | return functions->NewObjectArray(this,len,clazz,init);
1630 | }
1631 | jobject GetObjectArrayElement(jobjectArray array, jsize index) {
1632 | return functions->GetObjectArrayElement(this,array,index);
1633 | }
1634 | void SetObjectArrayElement(jobjectArray array, jsize index,
1635 | jobject val) {
1636 | functions->SetObjectArrayElement(this,array,index,val);
1637 | }
1638 |
1639 | jbooleanArray NewBooleanArray(jsize len) {
1640 | return functions->NewBooleanArray(this,len);
1641 | }
1642 | jbyteArray NewByteArray(jsize len) {
1643 | return functions->NewByteArray(this,len);
1644 | }
1645 | jcharArray NewCharArray(jsize len) {
1646 | return functions->NewCharArray(this,len);
1647 | }
1648 | jshortArray NewShortArray(jsize len) {
1649 | return functions->NewShortArray(this,len);
1650 | }
1651 | jintArray NewIntArray(jsize len) {
1652 | return functions->NewIntArray(this,len);
1653 | }
1654 | jlongArray NewLongArray(jsize len) {
1655 | return functions->NewLongArray(this,len);
1656 | }
1657 | jfloatArray NewFloatArray(jsize len) {
1658 | return functions->NewFloatArray(this,len);
1659 | }
1660 | jdoubleArray NewDoubleArray(jsize len) {
1661 | return functions->NewDoubleArray(this,len);
1662 | }
1663 |
1664 | jboolean * GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy) {
1665 | return functions->GetBooleanArrayElements(this,array,isCopy);
1666 | }
1667 | jbyte * GetByteArrayElements(jbyteArray array, jboolean *isCopy) {
1668 | return functions->GetByteArrayElements(this,array,isCopy);
1669 | }
1670 | jchar * GetCharArrayElements(jcharArray array, jboolean *isCopy) {
1671 | return functions->GetCharArrayElements(this,array,isCopy);
1672 | }
1673 | jshort * GetShortArrayElements(jshortArray array, jboolean *isCopy) {
1674 | return functions->GetShortArrayElements(this,array,isCopy);
1675 | }
1676 | jint * GetIntArrayElements(jintArray array, jboolean *isCopy) {
1677 | return functions->GetIntArrayElements(this,array,isCopy);
1678 | }
1679 | jlong * GetLongArrayElements(jlongArray array, jboolean *isCopy) {
1680 | return functions->GetLongArrayElements(this,array,isCopy);
1681 | }
1682 | jfloat * GetFloatArrayElements(jfloatArray array, jboolean *isCopy) {
1683 | return functions->GetFloatArrayElements(this,array,isCopy);
1684 | }
1685 | jdouble * GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy) {
1686 | return functions->GetDoubleArrayElements(this,array,isCopy);
1687 | }
1688 |
1689 | void ReleaseBooleanArrayElements(jbooleanArray array,
1690 | jboolean *elems,
1691 | jint mode) {
1692 | functions->ReleaseBooleanArrayElements(this,array,elems,mode);
1693 | }
1694 | void ReleaseByteArrayElements(jbyteArray array,
1695 | jbyte *elems,
1696 | jint mode) {
1697 | functions->ReleaseByteArrayElements(this,array,elems,mode);
1698 | }
1699 | void ReleaseCharArrayElements(jcharArray array,
1700 | jchar *elems,
1701 | jint mode) {
1702 | functions->ReleaseCharArrayElements(this,array,elems,mode);
1703 | }
1704 | void ReleaseShortArrayElements(jshortArray array,
1705 | jshort *elems,
1706 | jint mode) {
1707 | functions->ReleaseShortArrayElements(this,array,elems,mode);
1708 | }
1709 | void ReleaseIntArrayElements(jintArray array,
1710 | jint *elems,
1711 | jint mode) {
1712 | functions->ReleaseIntArrayElements(this,array,elems,mode);
1713 | }
1714 | void ReleaseLongArrayElements(jlongArray array,
1715 | jlong *elems,
1716 | jint mode) {
1717 | functions->ReleaseLongArrayElements(this,array,elems,mode);
1718 | }
1719 | void ReleaseFloatArrayElements(jfloatArray array,
1720 | jfloat *elems,
1721 | jint mode) {
1722 | functions->ReleaseFloatArrayElements(this,array,elems,mode);
1723 | }
1724 | void ReleaseDoubleArrayElements(jdoubleArray array,
1725 | jdouble *elems,
1726 | jint mode) {
1727 | functions->ReleaseDoubleArrayElements(this,array,elems,mode);
1728 | }
1729 |
1730 | void GetBooleanArrayRegion(jbooleanArray array,
1731 | jsize start, jsize len, jboolean *buf) {
1732 | functions->GetBooleanArrayRegion(this,array,start,len,buf);
1733 | }
1734 | void GetByteArrayRegion(jbyteArray array,
1735 | jsize start, jsize len, jbyte *buf) {
1736 | functions->GetByteArrayRegion(this,array,start,len,buf);
1737 | }
1738 | void GetCharArrayRegion(jcharArray array,
1739 | jsize start, jsize len, jchar *buf) {
1740 | functions->GetCharArrayRegion(this,array,start,len,buf);
1741 | }
1742 | void GetShortArrayRegion(jshortArray array,
1743 | jsize start, jsize len, jshort *buf) {
1744 | functions->GetShortArrayRegion(this,array,start,len,buf);
1745 | }
1746 | void GetIntArrayRegion(jintArray array,
1747 | jsize start, jsize len, jint *buf) {
1748 | functions->GetIntArrayRegion(this,array,start,len,buf);
1749 | }
1750 | void GetLongArrayRegion(jlongArray array,
1751 | jsize start, jsize len, jlong *buf) {
1752 | functions->GetLongArrayRegion(this,array,start,len,buf);
1753 | }
1754 | void GetFloatArrayRegion(jfloatArray array,
1755 | jsize start, jsize len, jfloat *buf) {
1756 | functions->GetFloatArrayRegion(this,array,start,len,buf);
1757 | }
1758 | void GetDoubleArrayRegion(jdoubleArray array,
1759 | jsize start, jsize len, jdouble *buf) {
1760 | functions->GetDoubleArrayRegion(this,array,start,len,buf);
1761 | }
1762 |
1763 | void SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len,
1764 | const jboolean *buf) {
1765 | functions->SetBooleanArrayRegion(this,array,start,len,buf);
1766 | }
1767 | void SetByteArrayRegion(jbyteArray array, jsize start, jsize len,
1768 | const jbyte *buf) {
1769 | functions->SetByteArrayRegion(this,array,start,len,buf);
1770 | }
1771 | void SetCharArrayRegion(jcharArray array, jsize start, jsize len,
1772 | const jchar *buf) {
1773 | functions->SetCharArrayRegion(this,array,start,len,buf);
1774 | }
1775 | void SetShortArrayRegion(jshortArray array, jsize start, jsize len,
1776 | const jshort *buf) {
1777 | functions->SetShortArrayRegion(this,array,start,len,buf);
1778 | }
1779 | void SetIntArrayRegion(jintArray array, jsize start, jsize len,
1780 | const jint *buf) {
1781 | functions->SetIntArrayRegion(this,array,start,len,buf);
1782 | }
1783 | void SetLongArrayRegion(jlongArray array, jsize start, jsize len,
1784 | const jlong *buf) {
1785 | functions->SetLongArrayRegion(this,array,start,len,buf);
1786 | }
1787 | void SetFloatArrayRegion(jfloatArray array, jsize start, jsize len,
1788 | const jfloat *buf) {
1789 | functions->SetFloatArrayRegion(this,array,start,len,buf);
1790 | }
1791 | void SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len,
1792 | const jdouble *buf) {
1793 | functions->SetDoubleArrayRegion(this,array,start,len,buf);
1794 | }
1795 |
1796 | jint RegisterNatives(jclass clazz, const JNINativeMethod *methods,
1797 | jint nMethods) {
1798 | return functions->RegisterNatives(this,clazz,methods,nMethods);
1799 | }
1800 | jint UnregisterNatives(jclass clazz) {
1801 | return functions->UnregisterNatives(this,clazz);
1802 | }
1803 |
1804 | jint MonitorEnter(jobject obj) {
1805 | return functions->MonitorEnter(this,obj);
1806 | }
1807 | jint MonitorExit(jobject obj) {
1808 | return functions->MonitorExit(this,obj);
1809 | }
1810 |
1811 | jint GetJavaVM(JavaVM **vm) {
1812 | return functions->GetJavaVM(this,vm);
1813 | }
1814 |
1815 | void GetStringRegion(jstring str, jsize start, jsize len, jchar *buf) {
1816 | functions->GetStringRegion(this,str,start,len,buf);
1817 | }
1818 | void GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf) {
1819 | functions->GetStringUTFRegion(this,str,start,len,buf);
1820 | }
1821 |
1822 | void * GetPrimitiveArrayCritical(jarray array, jboolean *isCopy) {
1823 | return functions->GetPrimitiveArrayCritical(this,array,isCopy);
1824 | }
1825 | void ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode) {
1826 | functions->ReleasePrimitiveArrayCritical(this,array,carray,mode);
1827 | }
1828 |
1829 | const jchar * GetStringCritical(jstring string, jboolean *isCopy) {
1830 | return functions->GetStringCritical(this,string,isCopy);
1831 | }
1832 | void ReleaseStringCritical(jstring string, const jchar *cstring) {
1833 | functions->ReleaseStringCritical(this,string,cstring);
1834 | }
1835 |
1836 | jweak NewWeakGlobalRef(jobject obj) {
1837 | return functions->NewWeakGlobalRef(this,obj);
1838 | }
1839 | void DeleteWeakGlobalRef(jweak ref) {
1840 | functions->DeleteWeakGlobalRef(this,ref);
1841 | }
1842 |
1843 | jboolean ExceptionCheck() {
1844 | return functions->ExceptionCheck(this);
1845 | }
1846 |
1847 | jobject NewDirectByteBuffer(void* address, jlong capacity) {
1848 | return functions->NewDirectByteBuffer(this, address, capacity);
1849 | }
1850 | void* GetDirectBufferAddress(jobject buf) {
1851 | return functions->GetDirectBufferAddress(this, buf);
1852 | }
1853 | jlong GetDirectBufferCapacity(jobject buf) {
1854 | return functions->GetDirectBufferCapacity(this, buf);
1855 | }
1856 | jobjectRefType GetObjectRefType(jobject obj) {
1857 | return functions->GetObjectRefType(this, obj);
1858 | }
1859 |
1860 | #endif /* __cplusplus */
1861 | };
1862 |
1863 | typedef struct JavaVMOption {
1864 | char *optionString;
1865 | void *extraInfo;
1866 | } JavaVMOption;
1867 |
1868 | typedef struct JavaVMInitArgs {
1869 | jint version;
1870 |
1871 | jint nOptions;
1872 | JavaVMOption *options;
1873 | jboolean ignoreUnrecognized;
1874 | } JavaVMInitArgs;
1875 |
1876 | typedef struct JavaVMAttachArgs {
1877 | jint version;
1878 |
1879 | char *name;
1880 | jobject group;
1881 | } JavaVMAttachArgs;
1882 |
1883 | /* These will be VM-specific. */
1884 |
1885 | #define JDK1_2
1886 | #define JDK1_4
1887 |
1888 | /* End VM-specific. */
1889 |
1890 | struct JNIInvokeInterface_ {
1891 | void *reserved0;
1892 | void *reserved1;
1893 | void *reserved2;
1894 |
1895 | jint (JNICALL *DestroyJavaVM)(JavaVM *vm);
1896 |
1897 | jint (JNICALL *AttachCurrentThread)(JavaVM *vm, void **penv, void *args);
1898 |
1899 | jint (JNICALL *DetachCurrentThread)(JavaVM *vm);
1900 |
1901 | jint (JNICALL *GetEnv)(JavaVM *vm, void **penv, jint version);
1902 |
1903 | jint (JNICALL *AttachCurrentThreadAsDaemon)(JavaVM *vm, void **penv, void *args);
1904 | };
1905 |
1906 | struct JavaVM_ {
1907 | const struct JNIInvokeInterface_ *functions;
1908 | #ifdef __cplusplus
1909 |
1910 | jint DestroyJavaVM() {
1911 | return functions->DestroyJavaVM(this);
1912 | }
1913 | jint AttachCurrentThread(void **penv, void *args) {
1914 | return functions->AttachCurrentThread(this, penv, args);
1915 | }
1916 | jint DetachCurrentThread() {
1917 | return functions->DetachCurrentThread(this);
1918 | }
1919 |
1920 | jint GetEnv(void **penv, jint version) {
1921 | return functions->GetEnv(this, penv, version);
1922 | }
1923 | jint AttachCurrentThreadAsDaemon(void **penv, void *args) {
1924 | return functions->AttachCurrentThreadAsDaemon(this, penv, args);
1925 | }
1926 | #endif
1927 | };
1928 |
1929 | #ifdef _JNI_IMPLEMENTATION_
1930 | #define _JNI_IMPORT_OR_EXPORT_ JNIEXPORT
1931 | #else
1932 | #define _JNI_IMPORT_OR_EXPORT_ JNIIMPORT
1933 | #endif
1934 | _JNI_IMPORT_OR_EXPORT_ jint JNICALL
1935 | JNI_GetDefaultJavaVMInitArgs(void *args);
1936 |
1937 | _JNI_IMPORT_OR_EXPORT_ jint JNICALL
1938 | JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args);
1939 |
1940 | _JNI_IMPORT_OR_EXPORT_ jint JNICALL
1941 | JNI_GetCreatedJavaVMs(JavaVM **, jsize, jsize *);
1942 |
1943 | /* Defined by native libraries. */
1944 | JNIEXPORT jint JNICALL
1945 | JNI_OnLoad(JavaVM *vm, void *reserved);
1946 |
1947 | JNIEXPORT void JNICALL
1948 | JNI_OnUnload(JavaVM *vm, void *reserved);
1949 |
1950 | #define JNI_VERSION_1_1 0x00010001
1951 | #define JNI_VERSION_1_2 0x00010002
1952 | #define JNI_VERSION_1_4 0x00010004
1953 | #define JNI_VERSION_1_6 0x00010006
1954 | #define JNI_VERSION_1_8 0x00010008
1955 |
1956 | #ifdef __cplusplus
1957 | } /* extern "C" */
1958 | #endif /* __cplusplus */
1959 |
1960 | #endif /* !_JAVASOFT_JNI_H_ */
1961 |
--------------------------------------------------------------------------------
/jni_md.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved.
3 | * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4 | *
5 | *
6 | *
7 | *
8 | *
9 | *
10 | *
11 | *
12 | *
13 | *
14 | *
15 | *
16 | *
17 | *
18 | *
19 | *
20 | *
21 | *
22 | *
23 | *
24 | */
25 |
26 | #ifndef _JAVASOFT_JNI_MD_H_
27 | #define _JAVASOFT_JNI_MD_H_
28 |
29 | #define JNIEXPORT __declspec(dllexport)
30 | #define JNIIMPORT __declspec(dllimport)
31 | #define JNICALL __stdcall
32 |
33 | typedef long jint;
34 | typedef __int64 jlong;
35 | typedef signed char jbyte;
36 |
37 | #endif /* !_JAVASOFT_JNI_MD_H_ */
38 |
--------------------------------------------------------------------------------
/jvm_dumper.c:
--------------------------------------------------------------------------------
1 | #include "jvm_dumper.h"
2 | #include "MinHook.h"
3 | #include
4 |
5 |
6 | const char* folderName = "C:\\JavaClassDump\\";
7 |
8 | /* Convert java string to UTF char*. Use local buffer if possible,
9 | otherwise malloc new memory. Returns null IFF malloc failed. */
10 | static char* getUTF(JNIEnv* env, jstring str, char* localBuf, int bufSize)
11 | {
12 | char* utfStr = NULL;
13 |
14 | int len = (*env)->GetStringUTFLength(env, str);
15 | int unicode_len = (*env)->GetStringLength(env, str);
16 | if (len >= bufSize) {
17 | utfStr = malloc(len + 1);
18 | if (utfStr == NULL) {
19 | return NULL;
20 | }
21 | }
22 | else {
23 | utfStr = localBuf;
24 | }
25 | (*env)->GetStringUTFRegion(env, str, 0, unicode_len, utfStr);
26 |
27 | return utfStr;
28 | }
29 |
30 |
31 | #define SKIP_JAVA_CLASSES = true;
32 |
33 | jclass JNICALL hookedDefineClass(JNIEnv* env, jobject loader, jstring name, jbyteArray data, jint offset, jint length, jobject pd, jstring source) {
34 | if (data == NULL || length < 0) {
35 | return defineClassV_(env, loader, name, data, offset, length, pd, source);
36 | }
37 | jbyte* body = (jbyte*)malloc(length);
38 | if (body == NULL) {
39 | perror("Malloc failed, OutOfMemory exception!");
40 | return;
41 | }
42 | (*env)->GetByteArrayRegion(env, data, offset, length, body);
43 | if ((*env)->ExceptionOccurred(env)) {
44 | goto free_mem;
45 | }
46 |
47 | const char* utfName;
48 | char buf[128];
49 |
50 | if (name != NULL) {
51 | utfName = getUTF(env, name, buf, sizeof(buf));
52 | if (utfName == NULL) {
53 | goto free_mem;
54 | }
55 | }
56 | else {
57 | goto free_mem;
58 | }
59 | printf("Class name %s\n", utfName);
60 | #ifdef SKIP_JAVA_CLASSES
61 | if (strstr(utfName, "java.lang")) {
62 | goto free_mem;
63 | }
64 | #endif
65 | char finalName[128];
66 | snprintf(finalName, 128, "%s.class", utfName);
67 | char fullPath[1024];
68 | snprintf(fullPath, 1024, "%s%s", folderName, finalName);
69 | FILE* out = fopen(fullPath, "wb");
70 | fwrite(body, 1, (*env)->GetArrayLength(env, data), out);
71 | fclose(out);
72 | goto free_mem;
73 | free_mem:
74 | free(body);
75 | return defineClassV_(env, loader, name, data, offset, length, pd, source);
76 | }
77 |
78 |
79 | boolean started = 0;
80 |
81 | void hookSetup(void) {
82 | if (started) return;
83 | started = 1;
84 | AllocConsole();
85 | FILE* fIn;
86 | FILE* fOut;
87 | freopen_s(&fIn, "conin$", "r", stdin);
88 | freopen_s(&fOut, "conout$", "w", stdout);
89 | freopen_s(&fOut, "conout$", "w", stderr);
90 | if (MH_Initialize() != MH_OK) {
91 | puts("Error while initializing hooks!");
92 | return;
93 | }
94 | HMODULE module = GetModuleHandleA("java.dll");
95 | if (!module) {
96 | puts("java.dll module not found!");
97 | return;
98 | }
99 | void* defineClass = (void*)GetProcAddress(module, "Java_java_lang_ClassLoader_defineClass1");
100 | if (!defineClass) {
101 | puts("defineClass function not found!");
102 | return;
103 | }
104 | if (MH_CreateHook((void*)defineClass, (void*)hookedDefineClass, (void**)(&defineClassV_)) != MH_OK) {
105 | puts("Creating hook failed!");
106 | return;
107 | }
108 | if (MH_EnableHook((void*)defineClass) != MH_OK) {
109 | puts("Enabling hook failed!");
110 | return;
111 | }
112 | CreateDirectoryA(folderName, NULL);
113 | puts("Java Runtime Class Dumper created by TheEasyPeasy (https://github.com/TheEasyPeasy)");
114 | }
115 |
--------------------------------------------------------------------------------
/jvm_dumper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "jni.h"
4 | #include "jni_md.h"
5 |
6 | typedef __int64(__fastcall *DefineClassV)(JNIEnv* env, jobject loader, jstring name, jbyteArray data, jint offset, jint length, jobject pd, jstring source);
7 | DefineClassV defineClassV_;
8 |
9 | void hookSetup(void);
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/pch.cpp:
--------------------------------------------------------------------------------
1 | // pch.cpp: plik źródłowy odpowiadający wstępnie skompilowanemu nagłówkowi
2 |
3 | #include "pch.h"
4 |
5 | // W przypadku korzystania ze wstępnie skompilowanych nagłówków ten plik źródłowy jest niezbędny, aby kompilacja powiodła się.
6 |
--------------------------------------------------------------------------------
/pch.h:
--------------------------------------------------------------------------------
1 | // pch.h: wstępnie skompilowany plik nagłówka.
2 | // Wymienione poniżej pliki są kompilowane tylko raz, co poprawia wydajność kompilacji dla przyszłych kompilacji.
3 | // Ma to także wpływ na wydajność funkcji IntelliSense, w tym uzupełnianie kodu i wiele funkcji przeglądania kodu.
4 | // Jednak WSZYSTKIE wymienione tutaj pliki będą ponownie kompilowane, jeśli którykolwiek z nich zostanie zaktualizowany między kompilacjami.
5 | // Nie dodawaj tutaj plików, które będziesz często aktualizować (obniża to korzystny wpływ na wydajność).
6 |
7 | #ifndef PCH_H
8 | #define PCH_H
9 |
10 | // w tym miejscu dodaj nagłówki, które mają być wstępnie kompilowane
11 | #include "framework.h"
12 |
13 | #endif //PCH_H
14 |
--------------------------------------------------------------------------------
/pstdint.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu. All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions
7 | * are met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | * 2. Redistributions in binary form must reproduce the above copyright
12 | * notice, this list of conditions and the following disclaimer in the
13 | * documentation and/or other materials provided with the distribution.
14 | *
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 | */
26 |
27 | #pragma once
28 |
29 | #include
30 |
31 | // Integer types for HDE.
32 | typedef INT8 int8_t;
33 | typedef INT16 int16_t;
34 | typedef INT32 int32_t;
35 | typedef INT64 int64_t;
36 | typedef UINT8 uint8_t;
37 | typedef UINT16 uint16_t;
38 | typedef UINT32 uint32_t;
39 | typedef UINT64 uint64_t;
40 |
--------------------------------------------------------------------------------
/table32.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 32 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #define C_NONE 0x00
9 | #define C_MODRM 0x01
10 | #define C_IMM8 0x02
11 | #define C_IMM16 0x04
12 | #define C_IMM_P66 0x10
13 | #define C_REL8 0x20
14 | #define C_REL32 0x40
15 | #define C_GROUP 0x80
16 | #define C_ERROR 0xff
17 |
18 | #define PRE_ANY 0x00
19 | #define PRE_NONE 0x01
20 | #define PRE_F2 0x02
21 | #define PRE_F3 0x04
22 | #define PRE_66 0x08
23 | #define PRE_67 0x10
24 | #define PRE_LOCK 0x20
25 | #define PRE_SEG 0x40
26 | #define PRE_ALL 0xff
27 |
28 | #define DELTA_OPCODES 0x4a
29 | #define DELTA_FPU_REG 0xf1
30 | #define DELTA_FPU_MODRM 0xf8
31 | #define DELTA_PREFIXES 0x130
32 | #define DELTA_OP_LOCK_OK 0x1a1
33 | #define DELTA_OP2_LOCK_OK 0x1b9
34 | #define DELTA_OP_ONLY_MEM 0x1cb
35 | #define DELTA_OP2_ONLY_MEM 0x1da
36 |
37 | unsigned char hde32_table[] = {
38 | 0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,0xa8,0xa3,
39 | 0xa8,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xac,0xaa,0xb2,0xaa,0x9f,0x9f,
40 | 0x9f,0x9f,0xb5,0xa3,0xa3,0xa4,0xaa,0xaa,0xba,0xaa,0x96,0xaa,0xa8,0xaa,0xc3,
41 | 0xc3,0x96,0x96,0xb7,0xae,0xd6,0xbd,0xa3,0xc5,0xa3,0xa3,0x9f,0xc3,0x9c,0xaa,
42 | 0xaa,0xac,0xaa,0xbf,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0x90,
43 | 0x82,0x7d,0x97,0x59,0x59,0x59,0x59,0x59,0x7f,0x59,0x59,0x60,0x7d,0x7f,0x7f,
44 | 0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x9a,0x88,0x7d,
45 | 0x59,0x50,0x50,0x50,0x50,0x59,0x59,0x59,0x59,0x61,0x94,0x61,0x9e,0x59,0x59,
46 | 0x85,0x59,0x92,0xa3,0x60,0x60,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,0x59,
47 | 0x59,0x59,0x9f,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xcc,0x01,0xbc,0x03,0xf0,
48 | 0x10,0x10,0x10,0x10,0x50,0x50,0x50,0x50,0x14,0x20,0x20,0x20,0x20,0x01,0x01,
49 | 0x01,0x01,0xc4,0x02,0x10,0x00,0x00,0x00,0x00,0x01,0x01,0xc0,0xc2,0x10,0x11,
50 | 0x02,0x03,0x11,0x03,0x03,0x04,0x00,0x00,0x14,0x00,0x02,0x00,0x00,0xc6,0xc8,
51 | 0x02,0x02,0x02,0x02,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0xca,
52 | 0x01,0x01,0x01,0x00,0x06,0x00,0x04,0x00,0xc0,0xc2,0x01,0x01,0x03,0x01,0xff,
53 | 0xff,0x01,0x00,0x03,0xc4,0xc4,0xc6,0x03,0x01,0x01,0x01,0xff,0x03,0x03,0x03,
54 | 0xc8,0x40,0x00,0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,
55 | 0x00,0x00,0x00,0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,
56 | 0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
57 | 0x00,0xff,0xff,0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
58 | 0x7f,0x00,0x00,0xff,0x4a,0x4a,0x4a,0x4a,0x4b,0x52,0x4a,0x4a,0x4a,0x4a,0x4f,
59 | 0x4c,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x55,0x45,0x40,0x4a,0x4a,0x4a,
60 | 0x45,0x59,0x4d,0x46,0x4a,0x5d,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,0x4a,
61 | 0x4a,0x4a,0x4a,0x4a,0x4a,0x61,0x63,0x67,0x4e,0x4a,0x4a,0x6b,0x6d,0x4a,0x4a,
62 | 0x45,0x6d,0x4a,0x4a,0x44,0x45,0x4a,0x4a,0x00,0x00,0x00,0x02,0x0d,0x06,0x06,
63 | 0x06,0x06,0x0e,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x00,0x06,0x06,0x02,0x06,
64 | 0x00,0x0a,0x0a,0x07,0x07,0x06,0x02,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
65 | 0x04,0x04,0x00,0x00,0x00,0x0e,0x05,0x06,0x06,0x06,0x01,0x06,0x00,0x00,0x08,
66 | 0x00,0x10,0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,
67 | 0x86,0x00,0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,
68 | 0xf8,0xbb,0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,
69 | 0xc4,0xff,0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,
70 | 0x13,0x09,0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,
71 | 0xb2,0xff,0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,
72 | 0xe7,0x08,0x00,0xf0,0x02,0x00
73 | };
74 |
--------------------------------------------------------------------------------
/table64.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hacker Disassembler Engine 64 C
3 | * Copyright (c) 2008-2009, Vyacheslav Patkov.
4 | * All rights reserved.
5 | *
6 | */
7 |
8 | #define C_NONE 0x00
9 | #define C_MODRM 0x01
10 | #define C_IMM8 0x02
11 | #define C_IMM16 0x04
12 | #define C_IMM_P66 0x10
13 | #define C_REL8 0x20
14 | #define C_REL32 0x40
15 | #define C_GROUP 0x80
16 | #define C_ERROR 0xff
17 |
18 | #define PRE_ANY 0x00
19 | #define PRE_NONE 0x01
20 | #define PRE_F2 0x02
21 | #define PRE_F3 0x04
22 | #define PRE_66 0x08
23 | #define PRE_67 0x10
24 | #define PRE_LOCK 0x20
25 | #define PRE_SEG 0x40
26 | #define PRE_ALL 0xff
27 |
28 | #define DELTA_OPCODES 0x4a
29 | #define DELTA_FPU_REG 0xfd
30 | #define DELTA_FPU_MODRM 0x104
31 | #define DELTA_PREFIXES 0x13c
32 | #define DELTA_OP_LOCK_OK 0x1ae
33 | #define DELTA_OP2_LOCK_OK 0x1c6
34 | #define DELTA_OP_ONLY_MEM 0x1d8
35 | #define DELTA_OP2_ONLY_MEM 0x1e7
36 |
37 | unsigned char hde64_table[] = {
38 | 0xa5,0xaa,0xa5,0xb8,0xa5,0xaa,0xa5,0xaa,0xa5,0xb8,0xa5,0xb8,0xa5,0xb8,0xa5,
39 | 0xb8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xac,0xc0,0xcc,0xc0,0xa1,0xa1,
40 | 0xa1,0xa1,0xb1,0xa5,0xa5,0xa6,0xc0,0xc0,0xd7,0xda,0xe0,0xc0,0xe4,0xc0,0xea,
41 | 0xea,0xe0,0xe0,0x98,0xc8,0xee,0xf1,0xa5,0xd3,0xa5,0xa5,0xa1,0xea,0x9e,0xc0,
42 | 0xc0,0xc2,0xc0,0xe6,0x03,0x7f,0x11,0x7f,0x01,0x7f,0x01,0x3f,0x01,0x01,0xab,
43 | 0x8b,0x90,0x64,0x5b,0x5b,0x5b,0x5b,0x5b,0x92,0x5b,0x5b,0x76,0x90,0x92,0x92,
44 | 0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x6a,0x73,0x90,
45 | 0x5b,0x52,0x52,0x52,0x52,0x5b,0x5b,0x5b,0x5b,0x77,0x7c,0x77,0x85,0x5b,0x5b,
46 | 0x70,0x5b,0x7a,0xaf,0x76,0x76,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,0x5b,
47 | 0x5b,0x5b,0x86,0x01,0x03,0x01,0x04,0x03,0xd5,0x03,0xd5,0x03,0xcc,0x01,0xbc,
48 | 0x03,0xf0,0x03,0x03,0x04,0x00,0x50,0x50,0x50,0x50,0xff,0x20,0x20,0x20,0x20,
49 | 0x01,0x01,0x01,0x01,0xc4,0x02,0x10,0xff,0xff,0xff,0x01,0x00,0x03,0x11,0xff,
50 | 0x03,0xc4,0xc6,0xc8,0x02,0x10,0x00,0xff,0xcc,0x01,0x01,0x01,0x00,0x00,0x00,
51 | 0x00,0x01,0x01,0x03,0x01,0xff,0xff,0xc0,0xc2,0x10,0x11,0x02,0x03,0x01,0x01,
52 | 0x01,0xff,0xff,0xff,0x00,0x00,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x10,
53 | 0x10,0x10,0x10,0x02,0x10,0x00,0x00,0xc6,0xc8,0x02,0x02,0x02,0x02,0x06,0x00,
54 | 0x04,0x00,0x02,0xff,0x00,0xc0,0xc2,0x01,0x01,0x03,0x03,0x03,0xca,0x40,0x00,
55 | 0x0a,0x00,0x04,0x00,0x00,0x00,0x00,0x7f,0x00,0x33,0x01,0x00,0x00,0x00,0x00,
56 | 0x00,0x00,0xff,0xbf,0xff,0xff,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0xff,0x00,
57 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,
58 | 0x00,0x00,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,
59 | 0xff,0x40,0x40,0x40,0x40,0x41,0x49,0x40,0x40,0x40,0x40,0x4c,0x42,0x40,0x40,
60 | 0x40,0x40,0x40,0x40,0x40,0x40,0x4f,0x44,0x53,0x40,0x40,0x40,0x44,0x57,0x43,
61 | 0x5c,0x40,0x60,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
62 | 0x40,0x40,0x64,0x66,0x6e,0x6b,0x40,0x40,0x6a,0x46,0x40,0x40,0x44,0x46,0x40,
63 | 0x40,0x5b,0x44,0x40,0x40,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x01,0x06,
64 | 0x06,0x02,0x06,0x06,0x00,0x06,0x00,0x0a,0x0a,0x00,0x00,0x00,0x02,0x07,0x07,
65 | 0x06,0x02,0x0d,0x06,0x06,0x06,0x0e,0x05,0x05,0x02,0x02,0x00,0x00,0x04,0x04,
66 | 0x04,0x04,0x05,0x06,0x06,0x06,0x00,0x00,0x00,0x0e,0x00,0x00,0x08,0x00,0x10,
67 | 0x00,0x18,0x00,0x20,0x00,0x28,0x00,0x30,0x00,0x80,0x01,0x82,0x01,0x86,0x00,
68 | 0xf6,0xcf,0xfe,0x3f,0xab,0x00,0xb0,0x00,0xb1,0x00,0xb3,0x00,0xba,0xf8,0xbb,
69 | 0x00,0xc0,0x00,0xc1,0x00,0xc7,0xbf,0x62,0xff,0x00,0x8d,0xff,0x00,0xc4,0xff,
70 | 0x00,0xc5,0xff,0x00,0xff,0xff,0xeb,0x01,0xff,0x0e,0x12,0x08,0x00,0x13,0x09,
71 | 0x00,0x16,0x08,0x00,0x17,0x09,0x00,0x2b,0x09,0x00,0xae,0xff,0x07,0xb2,0xff,
72 | 0x00,0xb4,0xff,0x00,0xb5,0xff,0x00,0xc3,0x01,0x00,0xc7,0xff,0xbf,0xe7,0x08,
73 | 0x00,0xf0,0x02,0x00
74 | };
75 |
--------------------------------------------------------------------------------
/trampoline.c:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #include
30 |
31 | #ifdef _MSC_VER
32 | #include
33 | #endif
34 |
35 | #ifndef ARRAYSIZE
36 | #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
37 | #endif
38 |
39 | #if defined(_M_X64) || defined(__x86_64__)
40 | #include "hde64.h"
41 | typedef hde64s HDE;
42 | #define HDE_DISASM(code, hs) hde64_disasm(code, hs)
43 | #else
44 | #include "hde32.h"
45 | typedef hde32s HDE;
46 | #define HDE_DISASM(code, hs) hde32_disasm(code, hs)
47 | #endif
48 |
49 | #include "trampoline.h"
50 | #include "buffer.h"
51 |
52 | // Maximum size of a trampoline function.
53 | #if defined(_M_X64) || defined(__x86_64__)
54 | #define TRAMPOLINE_MAX_SIZE (MEMORY_SLOT_SIZE - sizeof(JMP_ABS))
55 | #else
56 | #define TRAMPOLINE_MAX_SIZE MEMORY_SLOT_SIZE
57 | #endif
58 |
59 | //-------------------------------------------------------------------------
60 | static BOOL IsCodePadding(LPBYTE pInst, UINT size)
61 | {
62 | UINT i;
63 |
64 | if (pInst[0] != 0x00 && pInst[0] != 0x90 && pInst[0] != 0xCC)
65 | return FALSE;
66 |
67 | for (i = 1; i < size; ++i)
68 | {
69 | if (pInst[i] != pInst[0])
70 | return FALSE;
71 | }
72 | return TRUE;
73 | }
74 |
75 | //-------------------------------------------------------------------------
76 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct)
77 | {
78 | #if defined(_M_X64) || defined(__x86_64__)
79 | CALL_ABS call = {
80 | 0xFF, 0x15, 0x00000002, // FF15 00000002: CALL [RIP+8]
81 | 0xEB, 0x08, // EB 08: JMP +10
82 | 0x0000000000000000ULL // Absolute destination address
83 | };
84 | JMP_ABS jmp = {
85 | 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
86 | 0x0000000000000000ULL // Absolute destination address
87 | };
88 | JCC_ABS jcc = {
89 | 0x70, 0x0E, // 7* 0E: J** +16
90 | 0xFF, 0x25, 0x00000000, // FF25 00000000: JMP [RIP+6]
91 | 0x0000000000000000ULL // Absolute destination address
92 | };
93 | #else
94 | CALL_REL call = {
95 | 0xE8, // E8 xxxxxxxx: CALL +5+xxxxxxxx
96 | 0x00000000 // Relative destination address
97 | };
98 | JMP_REL jmp = {
99 | 0xE9, // E9 xxxxxxxx: JMP +5+xxxxxxxx
100 | 0x00000000 // Relative destination address
101 | };
102 | JCC_REL jcc = {
103 | 0x0F, 0x80, // 0F8* xxxxxxxx: J** +6+xxxxxxxx
104 | 0x00000000 // Relative destination address
105 | };
106 | #endif
107 |
108 | UINT8 oldPos = 0;
109 | UINT8 newPos = 0;
110 | ULONG_PTR jmpDest = 0; // Destination address of an internal jump.
111 | BOOL finished = FALSE; // Is the function completed?
112 | #if defined(_M_X64) || defined(__x86_64__)
113 | UINT8 instBuf[16];
114 | #endif
115 |
116 | ct->patchAbove = FALSE;
117 | ct->nIP = 0;
118 |
119 | do
120 | {
121 | HDE hs;
122 | UINT copySize;
123 | LPVOID pCopySrc;
124 | ULONG_PTR pOldInst = (ULONG_PTR)ct->pTarget + oldPos;
125 | ULONG_PTR pNewInst = (ULONG_PTR)ct->pTrampoline + newPos;
126 |
127 | copySize = HDE_DISASM((LPVOID)pOldInst, &hs);
128 | if (hs.flags & F_ERROR)
129 | return FALSE;
130 |
131 | pCopySrc = (LPVOID)pOldInst;
132 | if (oldPos >= sizeof(JMP_REL))
133 | {
134 | // The trampoline function is long enough.
135 | // Complete the function with the jump to the target function.
136 | #if defined(_M_X64) || defined(__x86_64__)
137 | jmp.address = pOldInst;
138 | #else
139 | jmp.operand = (UINT32)(pOldInst - (pNewInst + sizeof(jmp)));
140 | #endif
141 | pCopySrc = &jmp;
142 | copySize = sizeof(jmp);
143 |
144 | finished = TRUE;
145 | }
146 | #if defined(_M_X64) || defined(__x86_64__)
147 | else if ((hs.modrm & 0xC7) == 0x05)
148 | {
149 | // Instructions using RIP relative addressing. (ModR/M = 00???101B)
150 |
151 | // Modify the RIP relative address.
152 | PUINT32 pRelAddr;
153 |
154 | // Avoid using memcpy to reduce the footprint.
155 | #ifndef _MSC_VER
156 | memcpy(instBuf, (LPBYTE)pOldInst, copySize);
157 | #else
158 | __movsb(instBuf, (LPBYTE)pOldInst, copySize);
159 | #endif
160 | pCopySrc = instBuf;
161 |
162 | // Relative address is stored at (instruction length - immediate value length - 4).
163 | pRelAddr = (PUINT32)(instBuf + hs.len - ((hs.flags & 0x3C) >> 2) - 4);
164 | *pRelAddr
165 | = (UINT32)((pOldInst + hs.len + (INT32)hs.disp.disp32) - (pNewInst + hs.len));
166 |
167 | // Complete the function if JMP (FF /4).
168 | if (hs.opcode == 0xFF && hs.modrm_reg == 4)
169 | finished = TRUE;
170 | }
171 | #endif
172 | else if (hs.opcode == 0xE8)
173 | {
174 | // Direct relative CALL
175 | ULONG_PTR dest = pOldInst + hs.len + (INT32)hs.imm.imm32;
176 | #if defined(_M_X64) || defined(__x86_64__)
177 | call.address = dest;
178 | #else
179 | call.operand = (UINT32)(dest - (pNewInst + sizeof(call)));
180 | #endif
181 | pCopySrc = &call;
182 | copySize = sizeof(call);
183 | }
184 | else if ((hs.opcode & 0xFD) == 0xE9)
185 | {
186 | // Direct relative JMP (EB or E9)
187 | ULONG_PTR dest = pOldInst + hs.len;
188 |
189 | if (hs.opcode == 0xEB) // isShort jmp
190 | dest += (INT8)hs.imm.imm8;
191 | else
192 | dest += (INT32)hs.imm.imm32;
193 |
194 | // Simply copy an internal jump.
195 | if ((ULONG_PTR)ct->pTarget <= dest
196 | && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
197 | {
198 | if (jmpDest < dest)
199 | jmpDest = dest;
200 | }
201 | else
202 | {
203 | #if defined(_M_X64) || defined(__x86_64__)
204 | jmp.address = dest;
205 | #else
206 | jmp.operand = (UINT32)(dest - (pNewInst + sizeof(jmp)));
207 | #endif
208 | pCopySrc = &jmp;
209 | copySize = sizeof(jmp);
210 |
211 | // Exit the function if it is not in the branch.
212 | finished = (pOldInst >= jmpDest);
213 | }
214 | }
215 | else if ((hs.opcode & 0xF0) == 0x70
216 | || (hs.opcode & 0xFC) == 0xE0
217 | || (hs.opcode2 & 0xF0) == 0x80)
218 | {
219 | // Direct relative Jcc
220 | ULONG_PTR dest = pOldInst + hs.len;
221 |
222 | if ((hs.opcode & 0xF0) == 0x70 // Jcc
223 | || (hs.opcode & 0xFC) == 0xE0) // LOOPNZ/LOOPZ/LOOP/JECXZ
224 | dest += (INT8)hs.imm.imm8;
225 | else
226 | dest += (INT32)hs.imm.imm32;
227 |
228 | // Simply copy an internal jump.
229 | if ((ULONG_PTR)ct->pTarget <= dest
230 | && dest < ((ULONG_PTR)ct->pTarget + sizeof(JMP_REL)))
231 | {
232 | if (jmpDest < dest)
233 | jmpDest = dest;
234 | }
235 | else if ((hs.opcode & 0xFC) == 0xE0)
236 | {
237 | // LOOPNZ/LOOPZ/LOOP/JCXZ/JECXZ to the outside are not supported.
238 | return FALSE;
239 | }
240 | else
241 | {
242 | UINT8 cond = ((hs.opcode != 0x0F ? hs.opcode : hs.opcode2) & 0x0F);
243 | #if defined(_M_X64) || defined(__x86_64__)
244 | // Invert the condition in x64 mode to simplify the conditional jump logic.
245 | jcc.opcode = 0x71 ^ cond;
246 | jcc.address = dest;
247 | #else
248 | jcc.opcode1 = 0x80 | cond;
249 | jcc.operand = (UINT32)(dest - (pNewInst + sizeof(jcc)));
250 | #endif
251 | pCopySrc = &jcc;
252 | copySize = sizeof(jcc);
253 | }
254 | }
255 | else if ((hs.opcode & 0xFE) == 0xC2)
256 | {
257 | // RET (C2 or C3)
258 |
259 | // Complete the function if not in a branch.
260 | finished = (pOldInst >= jmpDest);
261 | }
262 |
263 | // Can't alter the instruction length in a branch.
264 | if (pOldInst < jmpDest && copySize != hs.len)
265 | return FALSE;
266 |
267 | // Trampoline function is too large.
268 | if ((newPos + copySize) > TRAMPOLINE_MAX_SIZE)
269 | return FALSE;
270 |
271 | // Trampoline function has too many instructions.
272 | if (ct->nIP >= ARRAYSIZE(ct->oldIPs))
273 | return FALSE;
274 |
275 | ct->oldIPs[ct->nIP] = oldPos;
276 | ct->newIPs[ct->nIP] = newPos;
277 | ct->nIP++;
278 |
279 | // Avoid using memcpy to reduce the footprint.
280 | #ifndef _MSC_VER
281 | memcpy((LPBYTE)ct->pTrampoline + newPos, pCopySrc, copySize);
282 | #else
283 | __movsb((LPBYTE)ct->pTrampoline + newPos, (LPBYTE)pCopySrc, copySize);
284 | #endif
285 | newPos += copySize;
286 | oldPos += hs.len;
287 | }
288 | while (!finished);
289 |
290 | // Is there enough place for a long jump?
291 | if (oldPos < sizeof(JMP_REL)
292 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL) - oldPos))
293 | {
294 | // Is there enough place for a short jump?
295 | if (oldPos < sizeof(JMP_REL_SHORT)
296 | && !IsCodePadding((LPBYTE)ct->pTarget + oldPos, sizeof(JMP_REL_SHORT) - oldPos))
297 | {
298 | return FALSE;
299 | }
300 |
301 | // Can we place the long jump above the function?
302 | if (!IsExecutableAddress((LPBYTE)ct->pTarget - sizeof(JMP_REL)))
303 | return FALSE;
304 |
305 | if (!IsCodePadding((LPBYTE)ct->pTarget - sizeof(JMP_REL), sizeof(JMP_REL)))
306 | return FALSE;
307 |
308 | ct->patchAbove = TRUE;
309 | }
310 |
311 | #if defined(_M_X64) || defined(__x86_64__)
312 | // Create a relay function.
313 | jmp.address = (ULONG_PTR)ct->pDetour;
314 |
315 | ct->pRelay = (LPBYTE)ct->pTrampoline + newPos;
316 | memcpy(ct->pRelay, &jmp, sizeof(jmp));
317 | #endif
318 |
319 | return TRUE;
320 | }
321 |
--------------------------------------------------------------------------------
/trampoline.h:
--------------------------------------------------------------------------------
1 | /*
2 | * MinHook - The Minimalistic API Hooking Library for x64/x86
3 | * Copyright (C) 2009-2017 Tsuda Kageyu.
4 | * All rights reserved.
5 | *
6 | * Redistribution and use in source and binary forms, with or without
7 | * modification, are permitted provided that the following conditions
8 | * are met:
9 | *
10 | * 1. Redistributions of source code must retain the above copyright
11 | * notice, this list of conditions and the following disclaimer.
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
19 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
20 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #pragma once
30 | #include
31 |
32 | #pragma pack(push, 1)
33 |
34 | // Structs for writing x86/x64 instructions.
35 |
36 | // 8-bit relative jump.
37 | typedef struct _JMP_REL_SHORT
38 | {
39 | UINT8 opcode; // EB xx: JMP +2+xx
40 | UINT8 operand;
41 | } JMP_REL_SHORT, *PJMP_REL_SHORT;
42 |
43 | // 32-bit direct relative jump/call.
44 | typedef struct _JMP_REL
45 | {
46 | UINT8 opcode; // E9/E8 xxxxxxxx: JMP/CALL +5+xxxxxxxx
47 | UINT32 operand; // Relative destination address
48 | } JMP_REL, *PJMP_REL, CALL_REL;
49 |
50 | // 64-bit indirect absolute jump.
51 | typedef struct _JMP_ABS
52 | {
53 | UINT8 opcode0; // FF25 00000000: JMP [+6]
54 | UINT8 opcode1;
55 | UINT32 dummy;
56 | UINT64 address; // Absolute destination address
57 | } JMP_ABS, *PJMP_ABS;
58 |
59 | // 64-bit indirect absolute call.
60 | typedef struct _CALL_ABS
61 | {
62 | UINT8 opcode0; // FF15 00000002: CALL [+6]
63 | UINT8 opcode1;
64 | UINT32 dummy0;
65 | UINT8 dummy1; // EB 08: JMP +10
66 | UINT8 dummy2;
67 | UINT64 address; // Absolute destination address
68 | } CALL_ABS;
69 |
70 | // 32-bit direct relative conditional jumps.
71 | typedef struct _JCC_REL
72 | {
73 | UINT8 opcode0; // 0F8* xxxxxxxx: J** +6+xxxxxxxx
74 | UINT8 opcode1;
75 | UINT32 operand; // Relative destination address
76 | } JCC_REL;
77 |
78 | // 64bit indirect absolute conditional jumps that x64 lacks.
79 | typedef struct _JCC_ABS
80 | {
81 | UINT8 opcode; // 7* 0E: J** +16
82 | UINT8 dummy0;
83 | UINT8 dummy1; // FF25 00000000: JMP [+6]
84 | UINT8 dummy2;
85 | UINT32 dummy3;
86 | UINT64 address; // Absolute destination address
87 | } JCC_ABS;
88 |
89 | #pragma pack(pop)
90 |
91 | typedef struct _TRAMPOLINE
92 | {
93 | LPVOID pTarget; // [In] Address of the target function.
94 | LPVOID pDetour; // [In] Address of the detour function.
95 | LPVOID pTrampoline; // [In] Buffer address for the trampoline and relay function.
96 |
97 | #if defined(_M_X64) || defined(__x86_64__)
98 | LPVOID pRelay; // [Out] Address of the relay function.
99 | #endif
100 | BOOL patchAbove; // [Out] Should use the hot patch area?
101 | UINT nIP; // [Out] Number of the instruction boundaries.
102 | UINT8 oldIPs[8]; // [Out] Instruction boundaries of the target function.
103 | UINT8 newIPs[8]; // [Out] Instruction boundaries of the trampoline function.
104 | } TRAMPOLINE, *PTRAMPOLINE;
105 |
106 | BOOL CreateTrampolineFunction(PTRAMPOLINE ct);
107 |
--------------------------------------------------------------------------------