├── bin
├── SuperF12.dll
└── SuperF12.exe
├── lib
└── SuperF12.lib
├── src
├── include
│ └── SuperF12.h
├── SuperF12.dll
│ ├── Common.h
│ ├── Common.cpp
│ ├── Globals.h
│ ├── resource.h
│ ├── DllMain.cpp
│ ├── Globals.cpp
│ ├── HookContext.h
│ ├── SuperF12.cpp
│ ├── DevToolsHost.h
│ ├── HookContext.cpp
│ ├── SuperF12.def
│ ├── SuperF12.dll.rc
│ ├── DevToolsHost.cpp
│ ├── Lock.cpp
│ ├── Lock.h
│ ├── SuperF12.dll.vcproj
│ └── Detours
│ │ ├── detours.h
│ │ ├── detours.cpp
│ │ └── disasm.cpp
├── SuperF12.exe
│ ├── Common.h
│ ├── Common.cpp
│ ├── Utility.h
│ ├── Version.h
│ ├── AttachDlg.cpp
│ ├── AttachDlg.h
│ ├── Utility.cpp
│ ├── WinMain.cpp
│ ├── res
│ │ ├── F12.cur
│ │ ├── toolbar.bmp
│ │ ├── SuperF12.ico
│ │ ├── manifest.xml
│ │ └── version.rc2
│ ├── SuperF12.exe.rc
│ ├── resource.h
│ └── SuperF12.exe.vcproj
└── SuperF12.sln
├── .gitignore
├── README.md
└── LICENSE
/bin/SuperF12.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/bin/SuperF12.dll
--------------------------------------------------------------------------------
/bin/SuperF12.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/bin/SuperF12.exe
--------------------------------------------------------------------------------
/lib/SuperF12.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/lib/SuperF12.lib
--------------------------------------------------------------------------------
/src/include/SuperF12.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/include/SuperF12.h
--------------------------------------------------------------------------------
/src/SuperF12.dll/Common.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/Common.h
--------------------------------------------------------------------------------
/src/SuperF12.exe/Common.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Common.h
--------------------------------------------------------------------------------
/src/SuperF12.dll/Common.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/Common.cpp
--------------------------------------------------------------------------------
/src/SuperF12.dll/Globals.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/Globals.h
--------------------------------------------------------------------------------
/src/SuperF12.dll/resource.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/resource.h
--------------------------------------------------------------------------------
/src/SuperF12.exe/Common.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Common.cpp
--------------------------------------------------------------------------------
/src/SuperF12.exe/Utility.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Utility.h
--------------------------------------------------------------------------------
/src/SuperF12.exe/Version.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Version.h
--------------------------------------------------------------------------------
/src/SuperF12.dll/DllMain.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/DllMain.cpp
--------------------------------------------------------------------------------
/src/SuperF12.dll/Globals.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/Globals.cpp
--------------------------------------------------------------------------------
/src/SuperF12.dll/HookContext.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/HookContext.h
--------------------------------------------------------------------------------
/src/SuperF12.dll/SuperF12.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/SuperF12.cpp
--------------------------------------------------------------------------------
/src/SuperF12.exe/AttachDlg.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/AttachDlg.cpp
--------------------------------------------------------------------------------
/src/SuperF12.exe/AttachDlg.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/AttachDlg.h
--------------------------------------------------------------------------------
/src/SuperF12.exe/Utility.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Utility.cpp
--------------------------------------------------------------------------------
/src/SuperF12.exe/WinMain.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/WinMain.cpp
--------------------------------------------------------------------------------
/src/SuperF12.exe/res/F12.cur:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/res/F12.cur
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Debug/
2 | Release/
3 |
4 | *.aps
5 | *.exp
6 | *.ncb
7 | *.pdb
8 | *.suo
9 | *.user
10 |
11 |
--------------------------------------------------------------------------------
/src/SuperF12.dll/DevToolsHost.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/DevToolsHost.h
--------------------------------------------------------------------------------
/src/SuperF12.dll/HookContext.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/HookContext.cpp
--------------------------------------------------------------------------------
/src/SuperF12.dll/SuperF12.def:
--------------------------------------------------------------------------------
1 | LIBRARY "SuperF12"
2 |
3 | EXPORTS
4 |
5 | InitSuperF12
6 | ShowDevTools
7 |
--------------------------------------------------------------------------------
/src/SuperF12.dll/SuperF12.dll.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/SuperF12.dll.rc
--------------------------------------------------------------------------------
/src/SuperF12.exe/SuperF12.exe.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/SuperF12.exe.rc
--------------------------------------------------------------------------------
/src/SuperF12.exe/res/toolbar.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/res/toolbar.bmp
--------------------------------------------------------------------------------
/src/SuperF12.dll/DevToolsHost.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/DevToolsHost.cpp
--------------------------------------------------------------------------------
/src/SuperF12.exe/res/SuperF12.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/res/SuperF12.ico
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SuperF12
2 | ========
3 |
4 | A powerful tool which can launch IE developer tools for all embedded IE windows.
5 |
--------------------------------------------------------------------------------
/src/SuperF12.exe/res/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SuperF12
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/SuperF12.exe/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by SuperF12.exe.rc
4 | //
5 | #define IDR_RT_MANIFEST 1
6 | #define IDI_ICON_MAIN 101
7 | #define IDC_CUR_F12 102
8 | #define IDD_DLG_ATTACH 201
9 | #define IDC_TREE 1001
10 | #define IDC_ST_INFO 1101
11 | #define IDC_ST_ARROW 1102
12 | #define IDC_ST_HWND 1103
13 |
14 | // Next default values for new objects
15 | //
16 | #ifdef APSTUDIO_INVOKED
17 | #ifndef APSTUDIO_READONLY_SYMBOLS
18 | #define _APS_NEXT_RESOURCE_VALUE 202
19 | #define _APS_NEXT_COMMAND_VALUE 40001
20 | #define _APS_NEXT_CONTROL_VALUE 1104
21 | #define _APS_NEXT_SYMED_VALUE 101
22 | #endif
23 | #endif
24 |
--------------------------------------------------------------------------------
/src/SuperF12.exe/res/version.rc2:
--------------------------------------------------------------------------------
1 | #include "..\Version.h"
2 |
3 | VS_VERSION_INFO VERSIONINFO
4 | FILEVERSION F12_RCVER
5 | PRODUCTVERSION F12_RCVER
6 | FILEFLAGSMASK 0x17L
7 | #ifdef _DEBUG
8 | FILEFLAGS 0x1L
9 | #else
10 | FILEFLAGS 0x0L
11 | #endif
12 | FILEOS 0x4L
13 | FILETYPE 0x1L
14 | FILESUBTYPE 0x0L
15 | BEGIN
16 | BLOCK "StringFileInfo"
17 | BEGIN
18 | BLOCK "080404b0"
19 | BEGIN
20 | VALUE "CompanyName", "Titi Studio"
21 | VALUE "FileDescription", "SuperF12"
22 | VALUE "FileVersion", F12_RCVERSTR
23 | VALUE "InternalName", "SuperF12"
24 | VALUE "LegalCopyright", "Copyright (C) 2001-2013"
25 | VALUE "OriginalFilename", "SuperF12.exe"
26 | VALUE "ProductName", "SuperF12"
27 | VALUE "ProductVersion", F12_RCVERSTR
28 | END
29 | END
30 | BLOCK "VarFileInfo"
31 | BEGIN
32 | VALUE "Translation", 0x804, 1200
33 | END
34 | END
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 titilima
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/src/SuperF12.dll/Lock.cpp:
--------------------------------------------------------------------------------
1 | #include "Common.h"
2 | #include "Lock.h"
3 |
4 | Lock::Lock(PCTSTR pszName) : m_cntReaders(0), m_hDataLock(CreateSemaphore(NULL, 1, 1, pszName))
5 | {
6 | ::InitializeCriticalSection(&m_cs);
7 | }
8 |
9 | Lock::~Lock(void)
10 | {
11 | CloseHandle(m_hDataLock);
12 | ::DeleteCriticalSection(&m_cs);
13 | }
14 |
15 | void Lock::AcquireForReading(void)
16 | {
17 | EnterCS();
18 | if (1 == ++m_cntReaders)
19 | {
20 | WaitForSingleObject(m_hDataLock, INFINITE);
21 | }
22 | LeaveCS();
23 | }
24 |
25 | void Lock::AcquireForWriting(void)
26 | {
27 | WaitForSingleObject(m_hDataLock, INFINITE);
28 | }
29 |
30 | void Lock::EnterCS(void)
31 | {
32 | ::EnterCriticalSection(&m_cs);
33 | }
34 |
35 | void Lock::LeaveCS(void)
36 | {
37 | ::LeaveCriticalSection(&m_cs);
38 | }
39 |
40 | void Lock::ReleaseForReading(void)
41 | {
42 | EnterCS();
43 | if (0 == --m_cntReaders)
44 | ReleaseSemaphore(m_hDataLock, 1, NULL);
45 | LeaveCS();
46 | }
47 |
48 | void Lock::ReleaseForWriting(void)
49 | {
50 | ReleaseSemaphore(m_hDataLock, 1, NULL);
51 | }
52 |
--------------------------------------------------------------------------------
/src/SuperF12.dll/Lock.h:
--------------------------------------------------------------------------------
1 | #ifndef LOCK_H
2 | #define LOCK_H
3 |
4 | #pragma once
5 |
6 | class Lock
7 | {
8 | public:
9 | Lock(PCTSTR pszName = NULL);
10 | ~Lock(void);
11 | public:
12 | void AcquireForReading(void);
13 | void AcquireForWriting(void);
14 | void AssertIsLocked(void);
15 | void ReleaseForReading(void);
16 | void ReleaseForWriting(void);
17 | private:
18 | void EnterCS(void);
19 | void LeaveCS(void);
20 | private:
21 | CRITICAL_SECTION m_cs;
22 | size_t m_cntReaders;
23 | HANDLE m_hDataLock;
24 | };
25 |
26 | class AutoReadLock
27 | {
28 | public:
29 | AutoReadLock(Lock& lock) : m_lock(lock)
30 | {
31 | m_lock.AcquireForReading();
32 | }
33 | ~AutoReadLock(void)
34 | {
35 | m_lock.ReleaseForReading();
36 | }
37 | private:
38 | Lock& m_lock;
39 | };
40 |
41 | class AutoWriteLock
42 | {
43 | public:
44 | AutoWriteLock(Lock& lock) : m_lock(lock)
45 | {
46 | m_lock.AcquireForWriting();
47 | }
48 | ~AutoWriteLock(void)
49 | {
50 | m_lock.ReleaseForWriting();
51 | }
52 | private:
53 | Lock& m_lock;
54 | };
55 |
56 | #endif // LOCK_H
57 |
--------------------------------------------------------------------------------
/src/SuperF12.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 10.00
3 | # Visual Studio 2008
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SuperF12.exe", "SuperF12.exe\SuperF12.exe.vcproj", "{9163D946-B9EB-4048-A61F-D43DC9D965EB}"
5 | EndProject
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SuperF12.dll", "SuperF12.dll\SuperF12.dll.vcproj", "{A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Win32 = Debug|Win32
11 | Release|Win32 = Release|Win32
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {9163D946-B9EB-4048-A61F-D43DC9D965EB}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {9163D946-B9EB-4048-A61F-D43DC9D965EB}.Debug|Win32.Build.0 = Debug|Win32
16 | {9163D946-B9EB-4048-A61F-D43DC9D965EB}.Release|Win32.ActiveCfg = Release|Win32
17 | {9163D946-B9EB-4048-A61F-D43DC9D965EB}.Release|Win32.Build.0 = Release|Win32
18 | {A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}.Debug|Win32.ActiveCfg = Debug|Win32
19 | {A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}.Debug|Win32.Build.0 = Debug|Win32
20 | {A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}.Release|Win32.ActiveCfg = Release|Win32
21 | {A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}.Release|Win32.Build.0 = Release|Win32
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | EndGlobal
27 |
--------------------------------------------------------------------------------
/src/SuperF12.exe/SuperF12.exe.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
26 |
29 |
32 |
35 |
38 |
41 |
53 |
56 |
59 |
62 |
73 |
76 |
79 |
82 |
85 |
88 |
91 |
94 |
95 |
103 |
106 |
109 |
112 |
115 |
118 |
130 |
133 |
136 |
139 |
152 |
155 |
158 |
161 |
164 |
167 |
170 |
174 |
175 |
176 |
177 |
178 |
179 |
184 |
187 |
188 |
191 |
194 |
198 |
199 |
202 |
206 |
207 |
208 |
211 |
212 |
215 |
216 |
217 |
222 |
225 |
226 |
229 |
230 |
233 |
234 |
237 |
238 |
241 |
242 |
243 |
248 |
251 |
252 |
255 |
256 |
259 |
260 |
263 |
264 |
267 |
268 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
--------------------------------------------------------------------------------
/src/SuperF12.dll/SuperF12.dll.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
26 |
29 |
32 |
35 |
38 |
41 |
54 |
57 |
60 |
63 |
76 |
79 |
82 |
85 |
88 |
91 |
94 |
97 |
98 |
106 |
109 |
112 |
115 |
118 |
121 |
134 |
137 |
140 |
143 |
158 |
161 |
164 |
167 |
170 |
173 |
176 |
180 |
181 |
182 |
183 |
184 |
185 |
190 |
193 |
196 |
200 |
201 |
204 |
208 |
209 |
210 |
213 |
214 |
217 |
220 |
224 |
225 |
228 |
232 |
233 |
234 |
237 |
238 |
241 |
242 |
245 |
246 |
249 |
250 |
253 |
254 |
255 |
260 |
263 |
264 |
267 |
268 |
271 |
272 |
275 |
276 |
279 |
280 |
283 |
284 |
287 |
288 |
289 |
294 |
297 |
298 |
299 |
302 |
305 |
308 |
314 |
315 |
318 |
324 |
325 |
326 |
329 |
330 |
333 |
336 |
342 |
343 |
346 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
--------------------------------------------------------------------------------
/src/SuperF12.dll/Detours/detours.h:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Core Detours Functionality (detours.h of detours.lib)
4 | //
5 | // Microsoft Research Detours Package, Version 3.0 Build_316.
6 | //
7 | // Copyright (c) Microsoft Corporation. All rights reserved.
8 | //
9 |
10 | #pragma once
11 | #ifndef _DETOURS_H_
12 | #define _DETOURS_H_
13 |
14 | #define DETOURS_VERSION 30000 // 3.00.00
15 |
16 | //////////////////////////////////////////////////////////////////////////////
17 | //
18 |
19 | #if (_MSC_VER < 1299)
20 | typedef LONG LONG_PTR;
21 | typedef ULONG ULONG_PTR;
22 | #endif
23 |
24 | #ifndef __in_z
25 | #define __in_z
26 | #endif
27 |
28 | //////////////////////////////////////////////////////////////////////////////
29 | //
30 | #ifndef GUID_DEFINED
31 | #define GUID_DEFINED
32 | typedef struct _GUID
33 | {
34 | DWORD Data1;
35 | WORD Data2;
36 | WORD Data3;
37 | BYTE Data4[ 8 ];
38 | } GUID;
39 |
40 | #ifdef INITGUID
41 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
42 | const GUID name \
43 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
44 | #else
45 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
46 | const GUID name
47 | #endif // INITGUID
48 | #endif // !GUID_DEFINED
49 |
50 | #if defined(__cplusplus)
51 | #ifndef _REFGUID_DEFINED
52 | #define _REFGUID_DEFINED
53 | #define REFGUID const GUID &
54 | #endif // !_REFGUID_DEFINED
55 | #else // !__cplusplus
56 | #ifndef _REFGUID_DEFINED
57 | #define _REFGUID_DEFINED
58 | #define REFGUID const GUID * const
59 | #endif // !_REFGUID_DEFINED
60 | #endif // !__cplusplus
61 |
62 | //
63 | //////////////////////////////////////////////////////////////////////////////
64 |
65 | #ifdef __cplusplus
66 | extern "C" {
67 | #endif // __cplusplus
68 |
69 | /////////////////////////////////////////////////// Instruction Target Macros.
70 | //
71 | #define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0)
72 | #define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1)
73 | #define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0"
74 |
75 | extern const GUID DETOUR_EXE_RESTORE_GUID;
76 | extern const GUID DETOUR_EXE_HELPER_GUID;
77 |
78 | #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr!
79 | typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE;
80 |
81 | /////////////////////////////////////////////////////////// Binary Structures.
82 | //
83 | #pragma pack(push, 8)
84 | typedef struct _DETOUR_SECTION_HEADER
85 | {
86 | DWORD cbHeaderSize;
87 | DWORD nSignature;
88 | DWORD nDataOffset;
89 | DWORD cbDataSize;
90 |
91 | DWORD nOriginalImportVirtualAddress;
92 | DWORD nOriginalImportSize;
93 | DWORD nOriginalBoundImportVirtualAddress;
94 | DWORD nOriginalBoundImportSize;
95 |
96 | DWORD nOriginalIatVirtualAddress;
97 | DWORD nOriginalIatSize;
98 | DWORD nOriginalSizeOfImage;
99 | DWORD cbPrePE;
100 |
101 | DWORD nOriginalClrFlags;
102 | DWORD reserved1;
103 | DWORD reserved2;
104 | DWORD reserved3;
105 |
106 | // Followed by cbPrePE bytes of data.
107 | } DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER;
108 |
109 | typedef struct _DETOUR_SECTION_RECORD
110 | {
111 | DWORD cbBytes;
112 | DWORD nReserved;
113 | GUID guid;
114 | } DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD;
115 |
116 | typedef struct _DETOUR_CLR_HEADER
117 | {
118 | // Header versioning
119 | ULONG cb;
120 | USHORT MajorRuntimeVersion;
121 | USHORT MinorRuntimeVersion;
122 |
123 | // Symbol table and startup information
124 | IMAGE_DATA_DIRECTORY MetaData;
125 | ULONG Flags;
126 |
127 | // Followed by the rest of the IMAGE_COR20_HEADER
128 | } DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER;
129 |
130 | typedef struct _DETOUR_EXE_RESTORE
131 | {
132 | DWORD cb;
133 | DWORD cbidh;
134 | DWORD cbinh;
135 | DWORD cbclr;
136 |
137 | PBYTE pidh;
138 | PBYTE pinh;
139 | PBYTE pclr;
140 |
141 | IMAGE_DOS_HEADER idh;
142 | union {
143 | IMAGE_NT_HEADERS inh;
144 | IMAGE_NT_HEADERS32 inh32;
145 | IMAGE_NT_HEADERS64 inh64;
146 | BYTE raw[sizeof(IMAGE_NT_HEADERS64) +
147 | sizeof(IMAGE_SECTION_HEADER) * 32];
148 | };
149 | DETOUR_CLR_HEADER clr;
150 |
151 | } DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE;
152 |
153 | typedef struct _DETOUR_EXE_HELPER
154 | {
155 | DWORD cb;
156 | DWORD pid;
157 | CHAR DllName[MAX_PATH];
158 |
159 | } DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER;
160 |
161 | #pragma pack(pop)
162 |
163 | #define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \
164 | { \
165 | sizeof(DETOUR_SECTION_HEADER),\
166 | DETOUR_SECTION_HEADER_SIGNATURE,\
167 | sizeof(DETOUR_SECTION_HEADER),\
168 | (cbSectionSize),\
169 | \
170 | 0,\
171 | 0,\
172 | 0,\
173 | 0,\
174 | \
175 | 0,\
176 | 0,\
177 | 0,\
178 | 0,\
179 | }
180 |
181 | /////////////////////////////////////////////////////////////// Helper Macros.
182 | //
183 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x)
184 | #define DETOURS_STRINGIFY_(x) #x
185 |
186 | ///////////////////////////////////////////////////////////// Binary Typedefs.
187 | //
188 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)(PVOID pContext,
189 | PCHAR pszFile,
190 | PCHAR *ppszOutFile);
191 |
192 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)(PVOID pContext,
193 | PCHAR pszOrigFile,
194 | PCHAR pszFile,
195 | PCHAR *ppszOutFile);
196 |
197 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)(PVOID pContext,
198 | ULONG nOrigOrdinal,
199 | ULONG nOrdinal,
200 | ULONG *pnOutOrdinal,
201 | PCHAR pszOrigSymbol,
202 | PCHAR pszSymbol,
203 | PCHAR *ppszOutSymbol);
204 |
205 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)(PVOID pContext);
206 |
207 | typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(PVOID pContext,
208 | ULONG nOrdinal,
209 | PCHAR pszName,
210 | PVOID pCode);
211 |
212 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(PVOID pContext,
213 | HMODULE hModule,
214 | PCSTR pszFile);
215 |
216 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(PVOID pContext,
217 | DWORD nOrdinal,
218 | PCSTR pszFunc,
219 | PVOID pvFunc);
220 |
221 | typedef VOID * PDETOUR_BINARY;
222 | typedef VOID * PDETOUR_LOADED_BINARY;
223 |
224 | //////////////////////////////////////////////////////////// Transaction APIs.
225 | //
226 | LONG WINAPI DetourTransactionBegin(VOID);
227 | LONG WINAPI DetourTransactionAbort(VOID);
228 | LONG WINAPI DetourTransactionCommit(VOID);
229 | LONG WINAPI DetourTransactionCommitEx(PVOID **pppFailedPointer);
230 |
231 | LONG WINAPI DetourUpdateThread(HANDLE hThread);
232 |
233 | LONG WINAPI DetourAttach(PVOID *ppPointer,
234 | PVOID pDetour);
235 |
236 | LONG WINAPI DetourAttachEx(PVOID *ppPointer,
237 | PVOID pDetour,
238 | PDETOUR_TRAMPOLINE *ppRealTrampoline,
239 | PVOID *ppRealTarget,
240 | PVOID *ppRealDetour);
241 |
242 | LONG WINAPI DetourDetach(PVOID *ppPointer,
243 | PVOID pDetour);
244 |
245 | BOOL WINAPI DetourSetIgnoreTooSmall(BOOL fIgnore);
246 | BOOL WINAPI DetourSetRetainRegions(BOOL fRetain);
247 |
248 | ////////////////////////////////////////////////////////////// Code Functions.
249 | //
250 | PVOID WINAPI DetourFindFunction(PCSTR pszModule, PCSTR pszFunction);
251 | PVOID WINAPI DetourCodeFromPointer(PVOID pPointer, PVOID *ppGlobals);
252 | PVOID WINAPI DetourCopyInstruction(PVOID pDst,
253 | PVOID *pDstPool,
254 | PVOID pSrc,
255 | PVOID *ppTarget,
256 | LONG *plExtra);
257 |
258 | ///////////////////////////////////////////////////// Loaded Binary Functions.
259 | //
260 | HMODULE WINAPI DetourGetContainingModule(PVOID pvAddr);
261 | HMODULE WINAPI DetourEnumerateModules(HMODULE hModuleLast);
262 | PVOID WINAPI DetourGetEntryPoint(HMODULE hModule);
263 | ULONG WINAPI DetourGetModuleSize(HMODULE hModule);
264 | BOOL WINAPI DetourEnumerateExports(HMODULE hModule,
265 | PVOID pContext,
266 | PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport);
267 | BOOL WINAPI DetourEnumerateImports(HMODULE hModule,
268 | PVOID pContext,
269 | PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile,
270 | PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc);
271 |
272 | PVOID WINAPI DetourFindPayload(HMODULE hModule, REFGUID rguid, DWORD *pcbData);
273 | PVOID WINAPI DetourFindPayloadEx(REFGUID rguid, DWORD * pcbData);
274 | DWORD WINAPI DetourGetSizeOfPayloads(HMODULE hModule);
275 |
276 | ///////////////////////////////////////////////// Persistent Binary Functions.
277 | //
278 |
279 | PDETOUR_BINARY WINAPI DetourBinaryOpen(HANDLE hFile);
280 | PVOID WINAPI DetourBinaryEnumeratePayloads(PDETOUR_BINARY pBinary,
281 | GUID *pGuid,
282 | DWORD *pcbData,
283 | DWORD *pnIterator);
284 | PVOID WINAPI DetourBinaryFindPayload(PDETOUR_BINARY pBinary,
285 | REFGUID rguid,
286 | DWORD *pcbData);
287 | PVOID WINAPI DetourBinarySetPayload(PDETOUR_BINARY pBinary,
288 | REFGUID rguid,
289 | PVOID pData,
290 | DWORD cbData);
291 | BOOL WINAPI DetourBinaryDeletePayload(PDETOUR_BINARY pBinary, REFGUID rguid);
292 | BOOL WINAPI DetourBinaryPurgePayloads(PDETOUR_BINARY pBinary);
293 | BOOL WINAPI DetourBinaryResetImports(PDETOUR_BINARY pBinary);
294 | BOOL WINAPI DetourBinaryEditImports(PDETOUR_BINARY pBinary,
295 | PVOID pContext,
296 | PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway,
297 | PF_DETOUR_BINARY_FILE_CALLBACK pfFile,
298 | PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol,
299 | PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit);
300 | BOOL WINAPI DetourBinaryWrite(PDETOUR_BINARY pBinary, HANDLE hFile);
301 | BOOL WINAPI DetourBinaryClose(PDETOUR_BINARY pBinary);
302 |
303 | /////////////////////////////////////////////////// Create Process & Load Dll.
304 | //
305 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)
306 | (LPCSTR lpApplicationName,
307 | LPSTR lpCommandLine,
308 | LPSECURITY_ATTRIBUTES lpProcessAttributes,
309 | LPSECURITY_ATTRIBUTES lpThreadAttributes,
310 | BOOL bInheritHandles,
311 | DWORD dwCreationFlags,
312 | LPVOID lpEnvironment,
313 | LPCSTR lpCurrentDirectory,
314 | LPSTARTUPINFOA lpStartupInfo,
315 | LPPROCESS_INFORMATION lpProcessInformation);
316 |
317 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)
318 | (LPCWSTR lpApplicationName,
319 | LPWSTR lpCommandLine,
320 | LPSECURITY_ATTRIBUTES lpProcessAttributes,
321 | LPSECURITY_ATTRIBUTES lpThreadAttributes,
322 | BOOL bInheritHandles,
323 | DWORD dwCreationFlags,
324 | LPVOID lpEnvironment,
325 | LPCWSTR lpCurrentDirectory,
326 | LPSTARTUPINFOW lpStartupInfo,
327 | LPPROCESS_INFORMATION lpProcessInformation);
328 |
329 | BOOL WINAPI DetourCreateProcessWithDllA(LPCSTR lpApplicationName,
330 | __in_z LPSTR lpCommandLine,
331 | LPSECURITY_ATTRIBUTES lpProcessAttributes,
332 | LPSECURITY_ATTRIBUTES lpThreadAttributes,
333 | BOOL bInheritHandles,
334 | DWORD dwCreationFlags,
335 | LPVOID lpEnvironment,
336 | LPCSTR lpCurrentDirectory,
337 | LPSTARTUPINFOA lpStartupInfo,
338 | LPPROCESS_INFORMATION lpProcessInformation,
339 | LPCSTR lpDllName,
340 | PDETOUR_CREATE_PROCESS_ROUTINEA
341 | pfCreateProcessA);
342 |
343 | BOOL WINAPI DetourCreateProcessWithDllW(LPCWSTR lpApplicationName,
344 | __in_z LPWSTR lpCommandLine,
345 | LPSECURITY_ATTRIBUTES lpProcessAttributes,
346 | LPSECURITY_ATTRIBUTES lpThreadAttributes,
347 | BOOL bInheritHandles,
348 | DWORD dwCreationFlags,
349 | LPVOID lpEnvironment,
350 | LPCWSTR lpCurrentDirectory,
351 | LPSTARTUPINFOW lpStartupInfo,
352 | LPPROCESS_INFORMATION lpProcessInformation,
353 | LPCSTR lpDllName,
354 | PDETOUR_CREATE_PROCESS_ROUTINEW
355 | pfCreateProcessW);
356 |
357 | #ifdef UNICODE
358 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllW
359 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW
360 | #else
361 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllA
362 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA
363 | #endif // !UNICODE
364 |
365 | BOOL WINAPI DetourCreateProcessWithDllExA(LPCSTR lpApplicationName,
366 | __in_z LPSTR lpCommandLine,
367 | LPSECURITY_ATTRIBUTES lpProcessAttributes,
368 | LPSECURITY_ATTRIBUTES lpThreadAttributes,
369 | BOOL bInheritHandles,
370 | DWORD dwCreationFlags,
371 | LPVOID lpEnvironment,
372 | LPCSTR lpCurrentDirectory,
373 | LPSTARTUPINFOA lpStartupInfo,
374 | LPPROCESS_INFORMATION lpProcessInformation,
375 | LPCSTR lpDllName,
376 | PDETOUR_CREATE_PROCESS_ROUTINEA
377 | pfCreateProcessA);
378 |
379 | BOOL WINAPI DetourCreateProcessWithDllExW(LPCWSTR lpApplicationName,
380 | __in_z LPWSTR lpCommandLine,
381 | LPSECURITY_ATTRIBUTES lpProcessAttributes,
382 | LPSECURITY_ATTRIBUTES lpThreadAttributes,
383 | BOOL bInheritHandles,
384 | DWORD dwCreationFlags,
385 | LPVOID lpEnvironment,
386 | LPCWSTR lpCurrentDirectory,
387 | LPSTARTUPINFOW lpStartupInfo,
388 | LPPROCESS_INFORMATION lpProcessInformation,
389 | LPCSTR lpDllName,
390 | PDETOUR_CREATE_PROCESS_ROUTINEW
391 | pfCreateProcessW);
392 |
393 | #ifdef UNICODE
394 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW
395 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW
396 | #else
397 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA
398 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA
399 | #endif // !UNICODE
400 |
401 | BOOL WINAPI DetourProcessViaHelperA(DWORD dwTargetPid,
402 | LPCSTR lpDllName,
403 | PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA);
404 |
405 | BOOL WINAPI DetourProcessViaHelperW(DWORD dwTargetPid,
406 | LPCSTR lpDllName,
407 | PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW);
408 |
409 | #ifdef UNICODE
410 | #define DetourProcessViaHelper DetourProcessViaHelperW
411 | #else
412 | #define DetourProcessViaHelper DetourProcessViaHelperA
413 | #endif // !UNICODE
414 |
415 | BOOL WINAPI DetourUpdateProcessWithDll(HANDLE hProcess,
416 | LPCSTR *plpDlls,
417 | DWORD nDlls);
418 |
419 | BOOL WINAPI DetourCopyPayloadToProcess(HANDLE hProcess,
420 | REFGUID rguid,
421 | PVOID pvData,
422 | DWORD cbData);
423 | BOOL WINAPI DetourRestoreAfterWith(VOID);
424 | BOOL WINAPI DetourRestoreAfterWithEx(PVOID pvData, DWORD cbData);
425 | BOOL WINAPI DetourIsHelperProcess(VOID);
426 | VOID CALLBACK DetourFinishHelperProcess(HWND, HINSTANCE, LPSTR, INT);
427 |
428 | //
429 | //////////////////////////////////////////////////////////////////////////////
430 | #ifdef __cplusplus
431 | }
432 | #endif // __cplusplus
433 |
434 | //////////////////////////////////////////////// Detours Internal Definitions.
435 | //
436 | #ifdef __cplusplus
437 | #ifdef DETOURS_INTERNAL
438 |
439 | #ifndef __deref_out
440 | #define __deref_out
441 | #endif
442 |
443 | #ifndef __deref
444 | #define __deref
445 | #endif
446 |
447 | //////////////////////////////////////////////////////////////////////////////
448 | //
449 | #if (_MSC_VER < 1299)
450 | #include
451 | typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64;
452 | typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64;
453 | typedef IMAGEHLP_SYMBOL SYMBOL_INFO;
454 | typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO;
455 |
456 | static inline
457 | LONG InterlockedCompareExchange(LONG *ptr, LONG nval, LONG oval)
458 | {
459 | return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval);
460 | }
461 | #else
462 | #include
463 | #endif
464 |
465 | #ifdef IMAGEAPI // defined by DBGHELP.H
466 | typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(LPAPI_VERSION AppVersion);
467 |
468 | typedef BOOL (NTAPI *PF_SymInitialize)(IN HANDLE hProcess,
469 | IN LPCSTR UserSearchPath,
470 | IN BOOL fInvadeProcess);
471 | typedef DWORD (NTAPI *PF_SymSetOptions)(IN DWORD SymOptions);
472 | typedef DWORD (NTAPI *PF_SymGetOptions)(VOID);
473 | typedef DWORD64 (NTAPI *PF_SymLoadModule64)(IN HANDLE hProcess,
474 | IN HANDLE hFile,
475 | IN PSTR ImageName,
476 | IN PSTR ModuleName,
477 | IN DWORD64 BaseOfDll,
478 | IN DWORD SizeOfDll);
479 | typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(IN HANDLE hProcess,
480 | IN DWORD64 qwAddr,
481 | OUT PIMAGEHLP_MODULE64 ModuleInfo);
482 | typedef BOOL (NTAPI *PF_SymFromName)(IN HANDLE hProcess,
483 | IN LPSTR Name,
484 | OUT PSYMBOL_INFO Symbol);
485 |
486 | typedef struct _DETOUR_SYM_INFO
487 | {
488 | HANDLE hProcess;
489 | HMODULE hDbgHelp;
490 | PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx;
491 | PF_SymInitialize pfSymInitialize;
492 | PF_SymSetOptions pfSymSetOptions;
493 | PF_SymGetOptions pfSymGetOptions;
494 | PF_SymLoadModule64 pfSymLoadModule64;
495 | PF_SymGetModuleInfo64 pfSymGetModuleInfo64;
496 | PF_SymFromName pfSymFromName;
497 | } DETOUR_SYM_INFO, *PDETOUR_SYM_INFO;
498 |
499 | PDETOUR_SYM_INFO DetourLoadDbgHelp(VOID);
500 |
501 | #endif // IMAGEAPI
502 |
503 | #ifndef DETOUR_TRACE
504 | #if DETOUR_DEBUG
505 | #define DETOUR_TRACE(x) printf x
506 | #define DETOUR_BREAK() __debugbreak()
507 | #include
508 | #include
509 | #else
510 | #define DETOUR_TRACE(x)
511 | #define DETOUR_BREAK()
512 | #endif
513 | #endif
514 |
515 | #ifdef DETOURS_IA64
516 | #error Feature not supported in this release.
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 | #endif // DETOURS_IA64
611 |
612 | #ifdef DETOURS_ARM
613 | #error Feature not supported in this release.
614 |
615 |
616 |
617 | #endif // DETOURS_ARM
618 |
619 | //////////////////////////////////////////////////////////////////////////////
620 |
621 | #endif // DETOURS_INTERNAL
622 | #endif // __cplusplus
623 |
624 | #endif // _DETOURS_H_
625 | //
626 | //////////////////////////////////////////////////////////////// End of File.
627 |
--------------------------------------------------------------------------------
/src/SuperF12.dll/Detours/detours.cpp:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Core Detours Functionality (detours.cpp of detours.lib)
4 | //
5 | // Microsoft Research Detours Package, Version 3.0 Build_316.
6 | //
7 | // Copyright (c) Microsoft Corporation. All rights reserved.
8 | //
9 | #include
10 |
11 | #if (_MSC_VER < 1299)
12 | #pragma warning(disable: 4710)
13 | #endif
14 |
15 | //#define DETOUR_DEBUG 1
16 | #define DETOURS_INTERNAL
17 |
18 | #include "detours.h"
19 |
20 | #if defined(DETOURS_X86)
21 | #elif defined(DETOURS_X64)
22 | #elif defined(DETOURS_IA64)
23 | #elif defined(DETOURS_ARM)
24 | #else
25 | #error Must define one of DETOURS_X86, DETOURS_X64, DETOURS_IA64, or DETOURS_ARM
26 | #endif
27 |
28 | #if !defined(DETOURS_32BIT) && !defined(DETOURS_64BIT)
29 | #error Must define one of DETOURS_32BIT or DETOURS_64BIT
30 | #endif
31 |
32 | //////////////////////////////////////////////////////////////////////////////
33 | //
34 | struct _DETOUR_ALIGN
35 | {
36 | BYTE obTarget : 3;
37 | BYTE obTrampoline : 5;
38 | };
39 |
40 | C_ASSERT(sizeof(_DETOUR_ALIGN) == 1);
41 |
42 | //////////////////////////////////////////////////////////////////////////////
43 | //
44 | static bool detour_is_imported(PBYTE pbCode, PBYTE pbAddress)
45 | {
46 | MEMORY_BASIC_INFORMATION mbi;
47 | VirtualQuery((PVOID)pbCode, &mbi, sizeof(mbi));
48 | __try {
49 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase;
50 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
51 | return false;
52 | }
53 |
54 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader +
55 | pDosHeader->e_lfanew);
56 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) {
57 | return false;
58 | }
59 |
60 | if (pbAddress >= ((PBYTE)pDosHeader +
61 | pNtHeader->OptionalHeader
62 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) &&
63 | pbAddress < ((PBYTE)pDosHeader +
64 | pNtHeader->OptionalHeader
65 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress +
66 | pNtHeader->OptionalHeader
67 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size)) {
68 | return true;
69 | }
70 | return false;
71 | }
72 | __except(EXCEPTION_EXECUTE_HANDLER) {
73 | return false;
74 | }
75 | }
76 |
77 | ///////////////////////////////////////////////////////////////////////// X86.
78 | //
79 | #ifdef DETOURS_X86
80 |
81 | struct _DETOUR_TRAMPOLINE
82 | {
83 | BYTE rbCode[30]; // target code + jmp to pbRemain
84 | BYTE cbCode; // size of moved target code.
85 | BYTE cbCodeBreak; // padding to make debugging easier.
86 | BYTE rbRestore[22]; // original target code.
87 | BYTE cbRestore; // size of original target code.
88 | BYTE cbRestoreBreak; // padding to make debugging easier.
89 | _DETOUR_ALIGN rAlign[8]; // instruction alignment array.
90 | PBYTE pbRemain; // first instruction after moved code. [free list]
91 | PBYTE pbDetour; // first instruction of detour function.
92 | };
93 |
94 | C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 72);
95 |
96 | enum {
97 | SIZE_OF_JMP = 5
98 | };
99 |
100 | inline PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE pbJmpVal)
101 | {
102 | PBYTE pbJmpSrc = pbCode + 5;
103 | *pbCode++ = 0xE9; // jmp +imm32
104 | *((INT32*&)pbCode)++ = (INT32)(pbJmpVal - pbJmpSrc);
105 | return pbCode;
106 | }
107 |
108 | inline PBYTE detour_gen_jmp_indirect(PBYTE pbCode, PBYTE *ppbJmpVal)
109 | {
110 | PBYTE pbJmpSrc = pbCode + 6;
111 | *pbCode++ = 0xff; // jmp [+imm32]
112 | *pbCode++ = 0x25;
113 | *((INT32*&)pbCode)++ = (INT32)((PBYTE)ppbJmpVal - pbJmpSrc);
114 | return pbCode;
115 | }
116 |
117 | inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit)
118 | {
119 | while (pbCode < pbLimit) {
120 | *pbCode++ = 0xcc; // brk;
121 | }
122 | return pbCode;
123 | }
124 |
125 | inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals)
126 | {
127 | if (pbCode == NULL) {
128 | return NULL;
129 | }
130 | if (ppGlobals != NULL) {
131 | *ppGlobals = NULL;
132 | }
133 |
134 | // First, skip over the import vector if there is one.
135 | if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32]
136 | // Looks like an import alias jump, then get the code it points to.
137 | PBYTE pbTarget = *(PBYTE *)&pbCode[2];
138 | if (detour_is_imported(pbCode, pbTarget)) {
139 | PBYTE pbNew = *(PBYTE *)pbTarget;
140 | DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew));
141 | pbCode = pbNew;
142 | }
143 | }
144 |
145 | // Then, skip over a patch jump
146 | if (pbCode[0] == 0xeb) { // jmp +imm8
147 | PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1];
148 | DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew));
149 | pbCode = pbNew;
150 |
151 | // First, skip over the import vector if there is one.
152 | if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32]
153 | // Looks like an import alias jump, then get the code it points to.
154 | PBYTE pbTarget = *(PBYTE *)&pbCode[2];
155 | if (detour_is_imported(pbCode, pbTarget)) {
156 | PBYTE pbNew = *(PBYTE *)pbTarget;
157 | DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew));
158 | pbCode = pbNew;
159 | }
160 | }
161 | // Finally, skip over a long jump if it is the target of the patch jump.
162 | else if (pbCode[0] == 0xe9) { // jmp +imm32
163 | PBYTE pbNew = pbCode + 5 + *(INT32 *)&pbCode[1];
164 | DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew));
165 | pbCode = pbNew;
166 | }
167 | }
168 | return pbCode;
169 | }
170 |
171 | inline BOOL detour_does_code_end_function(PBYTE pbCode)
172 | {
173 | if (pbCode[0] == 0xeb || // jmp +imm8
174 | pbCode[0] == 0xe9 || // jmp +imm32
175 | pbCode[0] == 0xe0 || // jmp eax
176 | pbCode[0] == 0xc2 || // ret +imm8
177 | pbCode[0] == 0xc3 || // ret
178 | pbCode[0] == 0xcc) { // brk
179 | return TRUE;
180 | }
181 | else if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32]
182 | return TRUE;
183 | }
184 | else if ((pbCode[0] == 0x26 || // jmp es:
185 | pbCode[0] == 0x2e || // jmp cs:
186 | pbCode[0] == 0x36 || // jmp ss:
187 | pbCode[0] == 0xe3 || // jmp ds:
188 | pbCode[0] == 0x64 || // jmp fs:
189 | pbCode[0] == 0x65) && // jmp gs:
190 | pbCode[1] == 0xff && // jmp [+imm32]
191 | pbCode[2] == 0x25) {
192 | return TRUE;
193 | }
194 | return FALSE;
195 | }
196 |
197 | inline ULONG detour_is_code_filler(PBYTE pbCode)
198 | {
199 | if (pbCode[0] == 0x90) { // nop
200 | return 1;
201 | }
202 | return 0;
203 | }
204 |
205 | #endif // DETOURS_X86
206 |
207 | ///////////////////////////////////////////////////////////////////////// X64.
208 | //
209 | #ifdef DETOURS_X64
210 | #error Feature not supported in this release.
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 | #endif // DETOURS_X64
339 |
340 | //////////////////////////////////////////////////////////////////////// IA64.
341 | //
342 | #ifdef DETOURS_IA64
343 | #error Feature not supported in this release.
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 |
445 |
446 |
447 |
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 |
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
468 |
469 |
470 |
471 |
472 |
473 |
474 |
475 |
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
494 |
495 |
496 |
497 |
498 |
499 | #endif // DETOURS_IA64
500 |
501 | #ifdef DETOURS_ARM
502 | #error Feature not supported in this release.
503 |
504 |
505 |
506 |
507 |
508 |
509 |
510 |
511 |
512 |
513 |
514 |
515 |
516 |
517 |
518 |
519 |
520 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 |
529 |
530 |
531 |
532 |
533 |
534 |
535 |
536 |
537 |
538 |
539 |
540 |
541 |
542 |
543 |
544 |
545 |
546 |
547 |
548 |
549 |
550 |
551 |
552 |
553 |
554 |
555 |
556 |
557 |
558 |
559 |
560 |
561 |
562 |
563 |
564 |
565 |
566 |
567 |
568 |
569 |
570 |
571 |
572 |
573 |
574 |
575 |
576 |
577 |
578 |
579 |
580 |
581 |
582 |
583 |
584 |
585 |
586 |
587 |
588 |
589 |
590 |
591 |
592 |
593 |
594 |
595 |
596 |
597 |
598 |
599 |
600 |
601 |
602 |
603 |
604 |
605 |
606 |
607 |
608 |
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 |
625 |
626 |
627 |
628 |
629 |
630 |
631 |
632 |
633 |
634 |
635 |
636 |
637 |
638 |
639 |
640 |
641 |
642 |
643 |
644 |
645 | #endif // DETOURS_ARM
646 |
647 | //////////////////////////////////////////////// Trampoline Memory Management.
648 | //
649 | struct DETOUR_REGION
650 | {
651 | ULONG dwSignature;
652 | DETOUR_REGION * pNext; // Next region in list of regions.
653 | DETOUR_TRAMPOLINE * pFree; // List of free trampolines in this region.
654 | };
655 | typedef DETOUR_REGION * PDETOUR_REGION;
656 |
657 | const ULONG DETOUR_REGION_SIGNATURE = 'Rrtd';
658 | const ULONG DETOUR_REGION_SIZE = 0x10000;
659 | const ULONG DETOUR_TRAMPOLINES_PER_REGION = (DETOUR_REGION_SIZE
660 | / sizeof(DETOUR_TRAMPOLINE)) - 1;
661 | static PDETOUR_REGION s_pRegions = NULL; // List of all regions.
662 | static PDETOUR_REGION s_pRegion = NULL; // Default region.
663 |
664 | static void detour_writable_trampoline_regions()
665 | {
666 | // Mark all of the regions as writable.
667 | for (PDETOUR_REGION pRegion = s_pRegions; pRegion != NULL; pRegion = pRegion->pNext) {
668 | DWORD dwOld;
669 | VirtualProtect(pRegion, DETOUR_REGION_SIZE, PAGE_EXECUTE_READWRITE, &dwOld);
670 | }
671 | }
672 |
673 | static void detour_runnable_trampoline_regions()
674 | {
675 | HANDLE hProcess = GetCurrentProcess();
676 |
677 | // Mark all of the regions as executable.
678 | for (PDETOUR_REGION pRegion = s_pRegions; pRegion != NULL; pRegion = pRegion->pNext) {
679 | DWORD dwOld;
680 | VirtualProtect(pRegion, DETOUR_REGION_SIZE, PAGE_EXECUTE_READ, &dwOld);
681 | FlushInstructionCache(hProcess, pRegion, DETOUR_REGION_SIZE);
682 | }
683 | }
684 |
685 | static PBYTE detour_alloc_round_down_to_region(PBYTE pbTry)
686 | {
687 | // WinXP64 returns free areas that aren't REGION aligned to 32-bit applications.
688 | ULONG_PTR extra = ((ULONG_PTR)pbTry) & (DETOUR_REGION_SIZE - 1);
689 | if (extra != 0) {
690 | pbTry -= extra;
691 | }
692 | return pbTry;
693 | }
694 |
695 | static PBYTE detour_alloc_round_up_to_region(PBYTE pbTry)
696 | {
697 | // WinXP64 returns free areas that aren't REGION aligned to 32-bit applications.
698 | ULONG_PTR extra = ((ULONG_PTR)pbTry) & (DETOUR_REGION_SIZE - 1);
699 | if (extra != 0) {
700 | ULONG_PTR adjust = DETOUR_REGION_SIZE - extra;
701 | pbTry += adjust;
702 | }
703 | return pbTry;
704 | }
705 |
706 | // Starting at pbLo, try to allocate a memory region, continue until pbHi.
707 |
708 | static PVOID detour_alloc_region_from_lo(PBYTE pbLo, PBYTE pbHi)
709 | {
710 | PBYTE pbTry = detour_alloc_round_up_to_region(pbLo);
711 |
712 | DETOUR_TRACE((" Looking for free region in %p..%p from %p:\n", pbLo, pbHi, pbTry));
713 |
714 | for (; pbTry < pbHi;) {
715 | MEMORY_BASIC_INFORMATION mbi;
716 |
717 | if (pbTry >= (PBYTE)(ULONG_PTR)0x50000000 &&
718 | pbTry <= (PBYTE)(ULONG_PTR)0x80000000) {
719 | // Skip region reserved for system DLLs.
720 | pbTry = (PBYTE)(ULONG_PTR)(0x80000000 + DETOUR_REGION_SIZE);
721 | continue;
722 | }
723 |
724 | ZeroMemory(&mbi, sizeof(mbi));
725 | if (!VirtualQuery(pbTry, &mbi, sizeof(mbi))) {
726 | break;
727 | }
728 |
729 | DETOUR_TRACE((" Try %p => %p..%p %6x\n",
730 | pbTry,
731 | mbi.BaseAddress,
732 | (PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
733 | mbi.State));
734 |
735 | if (mbi.State == MEM_FREE && mbi.RegionSize >= DETOUR_REGION_SIZE) {
736 |
737 | PVOID pv = VirtualAlloc(pbTry,
738 | DETOUR_REGION_SIZE,
739 | MEM_COMMIT|MEM_RESERVE,
740 | PAGE_EXECUTE_READWRITE);
741 | if (pv != NULL) {
742 | return pv;
743 | }
744 | pbTry += DETOUR_REGION_SIZE;
745 | }
746 | else {
747 | pbTry = detour_alloc_round_up_to_region((PBYTE)mbi.BaseAddress + mbi.RegionSize);
748 | }
749 | }
750 | return NULL;
751 | }
752 |
753 | // Starting at pbHi, try to allocate a memory region, continue until pbLo.
754 |
755 | static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi)
756 | {
757 | PBYTE pbTry = detour_alloc_round_down_to_region(pbHi - DETOUR_REGION_SIZE);
758 |
759 | DETOUR_TRACE((" Looking for free region in %p..%p from %p:\n", pbLo, pbHi, pbTry));
760 |
761 | for (; pbTry > pbLo;) {
762 | MEMORY_BASIC_INFORMATION mbi;
763 |
764 | DETOUR_TRACE((" Try %p\n", pbTry));
765 | if (pbTry >= (PBYTE)(ULONG_PTR)0x50000000 &&
766 | pbTry <= (PBYTE)(ULONG_PTR)0x80000000) {
767 | // Skip region reserved for system DLLs.
768 | pbTry = (PBYTE)(ULONG_PTR)(0x50000000 - DETOUR_REGION_SIZE);
769 | continue;
770 | }
771 |
772 | ZeroMemory(&mbi, sizeof(mbi));
773 | if (!VirtualQuery(pbTry, &mbi, sizeof(mbi))) {
774 | break;
775 | }
776 |
777 | DETOUR_TRACE((" Try %p => %p..%p %6x\n",
778 | pbTry,
779 | mbi.BaseAddress,
780 | (PBYTE)mbi.BaseAddress + mbi.RegionSize - 1,
781 | mbi.State));
782 |
783 | if (mbi.State == MEM_FREE && mbi.RegionSize >= DETOUR_REGION_SIZE) {
784 |
785 | PVOID pv = VirtualAlloc(pbTry,
786 | DETOUR_REGION_SIZE,
787 | MEM_COMMIT|MEM_RESERVE,
788 | PAGE_EXECUTE_READWRITE);
789 | if (pv != NULL) {
790 | return pv;
791 | }
792 | pbTry -= DETOUR_REGION_SIZE;
793 | }
794 | else {
795 | pbTry = detour_alloc_round_down_to_region((PBYTE)mbi.AllocationBase
796 | - DETOUR_REGION_SIZE);
797 | }
798 | }
799 | return NULL;
800 | }
801 |
802 | static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget)
803 | {
804 | // We have to place trampolines within +/- 2GB of target.
805 |
806 | PDETOUR_TRAMPOLINE pLo = (PDETOUR_TRAMPOLINE)
807 | ((pbTarget > (PBYTE)0x7ff80000)
808 | ? pbTarget - 0x7ff80000 : (PBYTE)(ULONG_PTR)DETOUR_REGION_SIZE);
809 | PDETOUR_TRAMPOLINE pHi = (PDETOUR_TRAMPOLINE)
810 | ((pbTarget < (PBYTE)0xffffffff80000000)
811 | ? pbTarget + 0x7ff80000 : (PBYTE)0xfffffffffff80000);
812 | DETOUR_TRACE(("[%p..%p..%p]\n", pLo, pbTarget, pHi));
813 |
814 | PDETOUR_TRAMPOLINE pTrampoline = NULL;
815 |
816 | // Insure that there is a default region.
817 | if (s_pRegion == NULL && s_pRegions != NULL) {
818 | s_pRegion = s_pRegions;
819 | }
820 |
821 | // First check the default region for an valid free block.
822 | if (s_pRegion != NULL && s_pRegion->pFree != NULL &&
823 | s_pRegion->pFree >= pLo && s_pRegion->pFree <= pHi) {
824 |
825 | found_region:
826 | pTrampoline = s_pRegion->pFree;
827 | // do a last sanity check on region.
828 | if (pTrampoline < pLo || pTrampoline > pHi) {
829 | return NULL;
830 | }
831 | s_pRegion->pFree = (PDETOUR_TRAMPOLINE)pTrampoline->pbRemain;
832 | memset(pTrampoline, 0xcc, sizeof(*pTrampoline));
833 | return pTrampoline;
834 | }
835 |
836 | // Then check the existing regions for a valid free block.
837 | for (s_pRegion = s_pRegions; s_pRegion != NULL; s_pRegion = s_pRegion->pNext) {
838 | if (s_pRegion != NULL && s_pRegion->pFree != NULL &&
839 | s_pRegion->pFree >= pLo && s_pRegion->pFree <= pHi) {
840 | goto found_region;
841 | }
842 | }
843 |
844 | // We need to allocate a new region.
845 |
846 | // Round pbTarget down to 64KB block.
847 | pbTarget = pbTarget - (PtrToUlong(pbTarget) & 0xffff);
848 |
849 | PVOID pbTry = NULL;
850 |
851 | // Try looking 1GB below or lower.
852 | if (pbTry == NULL && pbTarget > (PBYTE)0x40000000) {
853 | pbTry = detour_alloc_region_from_hi((PBYTE)pLo, pbTarget - 0x40000000);
854 | }
855 | // Try looking 1GB above or higher.
856 | if (pbTry == NULL && pbTarget < (PBYTE)0xffffffff40000000) {
857 | pbTry = detour_alloc_region_from_lo(pbTarget + 0x40000000, (PBYTE)pHi);
858 | }
859 | // Try looking 1GB below or higher.
860 | if (pbTry == NULL && pbTarget > (PBYTE)0x40000000) {
861 | pbTry = detour_alloc_region_from_lo(pbTarget - 0x40000000, pbTarget);
862 | }
863 | // Try looking 1GB above or lower.
864 | if (pbTry == NULL && pbTarget < (PBYTE)0xffffffff40000000) {
865 | pbTry = detour_alloc_region_from_hi(pbTarget, pbTarget + 0x40000000);
866 | }
867 | // Try anything below.
868 | if (pbTry == NULL) {
869 | pbTry = detour_alloc_region_from_hi((PBYTE)pLo, pbTarget);
870 | }
871 | // try anything above.
872 | if (pbTry == NULL) {
873 | pbTry = detour_alloc_region_from_lo(pbTarget, (PBYTE)pHi);
874 | }
875 |
876 | if (pbTry != NULL) {
877 | s_pRegion = (DETOUR_REGION*)pbTry;
878 | s_pRegion->dwSignature = DETOUR_REGION_SIGNATURE;
879 | s_pRegion->pFree = NULL;
880 | s_pRegion->pNext = s_pRegions;
881 | s_pRegions = s_pRegion;
882 | DETOUR_TRACE((" Allocated region %p..%p\n\n",
883 | s_pRegion, ((PBYTE)s_pRegion) + DETOUR_REGION_SIZE - 1));
884 |
885 | // Put everything but the first trampoline on the free list.
886 | PBYTE pFree = NULL;
887 | pTrampoline = ((PDETOUR_TRAMPOLINE)s_pRegion) + 1;
888 | for (int i = DETOUR_TRAMPOLINES_PER_REGION - 1; i > 1; i--) {
889 | pTrampoline[i].pbRemain = pFree;
890 | pFree = (PBYTE)&pTrampoline[i];
891 | }
892 | s_pRegion->pFree = (PDETOUR_TRAMPOLINE)pFree;
893 | goto found_region;
894 | }
895 |
896 | DETOUR_TRACE(("Couldn't find available memory region!\n"));
897 | return NULL;
898 | }
899 |
900 | static void detour_free_trampoline(PDETOUR_TRAMPOLINE pTrampoline)
901 | {
902 | PDETOUR_REGION pRegion = (PDETOUR_REGION)
903 | ((ULONG_PTR)pTrampoline & ~(ULONG_PTR)0xffff);
904 |
905 | memset(pTrampoline, 0, sizeof(*pTrampoline));
906 | pTrampoline->pbRemain = (PBYTE)pRegion->pFree;
907 | pRegion->pFree = pTrampoline;
908 | }
909 |
910 | static BOOL detour_is_region_empty(PDETOUR_REGION pRegion)
911 | {
912 | // Stop if the region isn't a region (this would be bad).
913 | if (pRegion->dwSignature != DETOUR_REGION_SIGNATURE) {
914 | return FALSE;
915 | }
916 |
917 | PBYTE pbRegionBeg = (PBYTE)pRegion;
918 | PBYTE pbRegionLim = pbRegionBeg + DETOUR_REGION_SIZE;
919 |
920 | // Stop if any of the trampolines aren't free.
921 | PDETOUR_TRAMPOLINE pTrampoline = ((PDETOUR_TRAMPOLINE)pRegion) + 1;
922 | for (int i = 0; i < DETOUR_TRAMPOLINES_PER_REGION; i++) {
923 | if (pTrampoline[i].pbRemain != NULL &&
924 | (pTrampoline[i].pbRemain < pbRegionBeg ||
925 | pTrampoline[i].pbRemain >= pbRegionLim)) {
926 | return FALSE;
927 | }
928 | }
929 |
930 | // OK, the region is empty.
931 | return TRUE;
932 | }
933 |
934 | static void detour_free_unused_trampoline_regions()
935 | {
936 | PDETOUR_REGION *ppRegionBase = &s_pRegions;
937 | PDETOUR_REGION pRegion = s_pRegions;
938 |
939 | while (pRegion != NULL) {
940 | if (detour_is_region_empty(pRegion)) {
941 | *ppRegionBase = pRegion->pNext;
942 |
943 | VirtualFree(pRegion, 0, MEM_RELEASE);
944 | s_pRegion = NULL;
945 | }
946 | else {
947 | ppRegionBase = &pRegion->pNext;
948 | }
949 | pRegion = *ppRegionBase;
950 | }
951 | }
952 |
953 | ///////////////////////////////////////////////////////// Transaction Structs.
954 | //
955 | struct DetourThread
956 | {
957 | DetourThread * pNext;
958 | HANDLE hThread;
959 | };
960 |
961 | struct DetourOperation
962 | {
963 | DetourOperation * pNext;
964 | BOOL fIsRemove;
965 | PBYTE * ppbPointer;
966 | PBYTE pbTarget;
967 | PDETOUR_TRAMPOLINE pTrampoline;
968 | ULONG dwPerm;
969 | };
970 |
971 | static BOOL s_fIgnoreTooSmall = FALSE;
972 | static BOOL s_fRetainRegions = FALSE;
973 |
974 | static LONG s_nPendingThreadId = 0; // Thread owning pending transaction.
975 | static LONG s_nPendingError = NO_ERROR;
976 | static PVOID * s_ppPendingError = NULL;
977 | static DetourThread * s_pPendingThreads = NULL;
978 | static DetourOperation * s_pPendingOperations = NULL;
979 |
980 | //////////////////////////////////////////////////////////////////////////////
981 | //
982 | PVOID WINAPI DetourCodeFromPointer(PVOID pPointer, PVOID *ppGlobals)
983 | {
984 | return detour_skip_jmp((PBYTE)pPointer, ppGlobals);
985 | }
986 |
987 | //////////////////////////////////////////////////////////// Transaction APIs.
988 | //
989 | BOOL WINAPI DetourSetIgnoreTooSmall(BOOL fIgnore)
990 | {
991 | BOOL fPrevious = s_fIgnoreTooSmall;
992 | s_fIgnoreTooSmall = fIgnore;
993 | return fPrevious;
994 | }
995 |
996 | BOOL WINAPI DetourSetRetainRegions(BOOL fRetain)
997 | {
998 | BOOL fPrevious = s_fRetainRegions;
999 | s_fRetainRegions = fRetain;
1000 | return fPrevious;
1001 | }
1002 |
1003 | LONG WINAPI DetourTransactionBegin()
1004 | {
1005 | // Only one transaction is allowed at a time.
1006 | if (s_nPendingThreadId != 0) {
1007 | return ERROR_INVALID_OPERATION;
1008 | }
1009 | // Make sure only one thread can start a transaction.
1010 | if (InterlockedCompareExchange(&s_nPendingThreadId, (LONG)GetCurrentThreadId(), 0) != 0) {
1011 | return ERROR_INVALID_OPERATION;
1012 | }
1013 |
1014 | s_pPendingOperations = NULL;
1015 | s_pPendingThreads = NULL;
1016 | s_nPendingError = NO_ERROR;
1017 | s_ppPendingError = NULL;
1018 |
1019 | // Make sure the trampoline pages are writable.
1020 | detour_writable_trampoline_regions();
1021 |
1022 | return NO_ERROR;
1023 | }
1024 |
1025 | LONG WINAPI DetourTransactionAbort()
1026 | {
1027 | if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
1028 | return ERROR_INVALID_OPERATION;
1029 | }
1030 |
1031 | // Restore all of the page permissions.
1032 | for (DetourOperation *o = s_pPendingOperations; o != NULL;) {
1033 | // We don't care if this fails, because the code is still accessible.
1034 | DWORD dwOld;
1035 | VirtualProtect(o->pbTarget, o->pTrampoline->cbRestore,
1036 | o->dwPerm, &dwOld);
1037 |
1038 | if (!o->fIsRemove) {
1039 | if (o->pTrampoline) {
1040 | detour_free_trampoline(o->pTrampoline);
1041 | o->pTrampoline = NULL;
1042 | }
1043 | }
1044 |
1045 | DetourOperation *n = o->pNext;
1046 | delete o;
1047 | o = n;
1048 | }
1049 | s_pPendingOperations = NULL;
1050 |
1051 | // Make sure the trampoline pages are no longer writable.
1052 | detour_runnable_trampoline_regions();
1053 |
1054 | // Resume any suspended threads.
1055 | for (DetourThread *t = s_pPendingThreads; t != NULL;) {
1056 | // There is nothing we can do if this fails.
1057 | ResumeThread(t->hThread);
1058 |
1059 | DetourThread *n = t->pNext;
1060 | delete t;
1061 | t = n;
1062 | }
1063 | s_pPendingThreads = NULL;
1064 | s_nPendingThreadId = 0;
1065 |
1066 | return NO_ERROR;
1067 | }
1068 |
1069 | LONG WINAPI DetourTransactionCommit()
1070 | {
1071 | return DetourTransactionCommitEx(NULL);
1072 | }
1073 |
1074 | static BYTE detour_align_from_trampoline(PDETOUR_TRAMPOLINE pTrampoline, BYTE obTrampoline)
1075 | {
1076 | for (LONG n = 0; n < ARRAYSIZE(pTrampoline->rAlign); n++) {
1077 | if (pTrampoline->rAlign[n].obTrampoline == obTrampoline) {
1078 | return pTrampoline->rAlign[n].obTarget;
1079 | }
1080 | }
1081 | return 0;
1082 | }
1083 |
1084 | static LONG detour_align_from_target(PDETOUR_TRAMPOLINE pTrampoline, LONG obTarget)
1085 | {
1086 | for (LONG n = 0; n < ARRAYSIZE(pTrampoline->rAlign); n++) {
1087 | if (pTrampoline->rAlign[n].obTarget == obTarget) {
1088 | return pTrampoline->rAlign[n].obTrampoline;
1089 | }
1090 | }
1091 | return 0;
1092 | }
1093 |
1094 | LONG WINAPI DetourTransactionCommitEx(PVOID **pppFailedPointer)
1095 | {
1096 | if (pppFailedPointer != NULL) {
1097 | // Used to get the last error.
1098 | *pppFailedPointer = s_ppPendingError;
1099 | }
1100 | if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
1101 | return ERROR_INVALID_OPERATION;
1102 | }
1103 |
1104 | // If any of the pending operations failed, then we abort the whole transaction.
1105 | if (s_nPendingError != NO_ERROR) {
1106 | DETOUR_BREAK();
1107 | DetourTransactionAbort();
1108 | return s_nPendingError;
1109 | }
1110 |
1111 | // Common variables.
1112 | DetourOperation *o;
1113 | DetourThread *t;
1114 | BOOL freed = FALSE;
1115 |
1116 | // Insert or remove each of the detours.
1117 | for (o = s_pPendingOperations; o != NULL; o = o->pNext) {
1118 | if (o->fIsRemove) {
1119 | CopyMemory(o->pbTarget,
1120 | o->pTrampoline->rbRestore,
1121 | o->pTrampoline->cbRestore);
1122 | #ifdef DETOURS_IA64
1123 | #error Feature not supported in this release.
1124 | #endif // DETOURS_IA64
1125 |
1126 | #ifdef DETOURS_X86
1127 | *o->ppbPointer = o->pbTarget;
1128 | #endif // DETOURS_X86
1129 |
1130 | #ifdef DETOURS_X64
1131 | #error Feature not supported in this release.
1132 | #endif // DETOURS_X64
1133 |
1134 | #ifdef DETOURS_ARM
1135 | #error Feature not supported in this release.
1136 | #endif // DETOURS_ARM
1137 | }
1138 | else {
1139 | DETOUR_TRACE(("detours: pbTramp =%p, pbRemain=%p, pbDetour=%p, cbRestore=%d\n",
1140 | o->pTrampoline,
1141 | o->pTrampoline->pbRemain,
1142 | o->pTrampoline->pbDetour,
1143 | o->pTrampoline->cbRestore));
1144 |
1145 | DETOUR_TRACE(("detours: pbTarget=%p: "
1146 | "%02x %02x %02x %02x "
1147 | "%02x %02x %02x %02x "
1148 | "%02x %02x %02x %02x [before]\n",
1149 | o->pbTarget,
1150 | o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3],
1151 | o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7],
1152 | o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11]));
1153 |
1154 | #ifdef DETOURS_IA64
1155 | #error Feature not supported in this release.
1156 |
1157 |
1158 | #endif // DETOURS_IA64
1159 |
1160 | #ifdef DETOURS_X64
1161 | #error Feature not supported in this release.
1162 |
1163 |
1164 |
1165 | #endif // DETOURS_X64
1166 |
1167 | #ifdef DETOURS_X86
1168 | PBYTE pbCode = detour_gen_jmp_immediate(o->pbTarget, o->pTrampoline->pbDetour);
1169 | pbCode = detour_gen_brk(pbCode, o->pTrampoline->pbRemain);
1170 | *o->ppbPointer = o->pTrampoline->rbCode;
1171 | #endif // DETOURS_X86
1172 |
1173 | #ifdef DETOURS_ARM
1174 | #error Feature not supported in this release.
1175 |
1176 |
1177 | #endif // DETOURS_ARM
1178 |
1179 | DETOUR_TRACE(("detours: pbTarget=%p: "
1180 | "%02x %02x %02x %02x "
1181 | "%02x %02x %02x %02x "
1182 | "%02x %02x %02x %02x [after]\n",
1183 | o->pbTarget,
1184 | o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3],
1185 | o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7],
1186 | o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11]));
1187 |
1188 | DETOUR_TRACE(("detours: pbTramp =%p: "
1189 | "%02x %02x %02x %02x "
1190 | "%02x %02x %02x %02x "
1191 | "%02x %02x %02x %02x\n",
1192 | o->pTrampoline,
1193 | o->pTrampoline->rbCode[0], o->pTrampoline->rbCode[1],
1194 | o->pTrampoline->rbCode[2], o->pTrampoline->rbCode[3],
1195 | o->pTrampoline->rbCode[4], o->pTrampoline->rbCode[5],
1196 | o->pTrampoline->rbCode[6], o->pTrampoline->rbCode[7],
1197 | o->pTrampoline->rbCode[8], o->pTrampoline->rbCode[9],
1198 | o->pTrampoline->rbCode[10], o->pTrampoline->rbCode[11]));
1199 |
1200 | #ifdef DETOURS_IA64
1201 | #error Feature not supported in this release.
1202 |
1203 |
1204 |
1205 |
1206 |
1207 |
1208 |
1209 |
1210 |
1211 |
1212 |
1213 |
1214 |
1215 |
1216 |
1217 |
1218 |
1219 |
1220 |
1221 |
1222 |
1223 |
1224 |
1225 |
1226 |
1227 |
1228 |
1229 |
1230 | #endif // DETOURS_IA64
1231 | }
1232 | }
1233 |
1234 | // Update any suspended threads.
1235 | for (t = s_pPendingThreads; t != NULL; t = t->pNext) {
1236 | CONTEXT cxt;
1237 | cxt.ContextFlags = CONTEXT_CONTROL;
1238 |
1239 | #undef DETOURS_EIP
1240 | #undef DETOURS_EIP_TYPE
1241 |
1242 | #ifdef DETOURS_X86
1243 | #define DETOURS_EIP Eip
1244 | #define DETOURS_EIP_TYPE DWORD
1245 | #endif // DETOURS_X86
1246 |
1247 | #ifdef DETOURS_X64
1248 | #error Feature not supported in this release.
1249 |
1250 | #endif // DETOURS_X64
1251 |
1252 | #ifdef DETOURS_IA64
1253 | #error Feature not supported in this release.
1254 |
1255 | #endif // DETOURS_IA64
1256 |
1257 | #ifdef DETOURS_ARM
1258 | #error Feature not supported in this release.
1259 |
1260 | #endif // DETOURS_ARM
1261 |
1262 | if (GetThreadContext(t->hThread, &cxt)) {
1263 | for (DetourOperation *o = s_pPendingOperations; o != NULL; o = o->pNext) {
1264 | if (o->fIsRemove) {
1265 | if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline &&
1266 | cxt.DETOURS_EIP < (DETOURS_EIP_TYPE)((ULONG_PTR)o->pTrampoline
1267 | + sizeof(o->pTrampoline))
1268 | ) {
1269 |
1270 | cxt.DETOURS_EIP = (DETOURS_EIP_TYPE)
1271 | ((ULONG_PTR)o->pbTarget
1272 | + detour_align_from_trampoline(o->pTrampoline,
1273 | (BYTE)(cxt.DETOURS_EIP
1274 | - (DETOURS_EIP_TYPE)(ULONG_PTR)
1275 | o->pTrampoline)));
1276 |
1277 | SetThreadContext(t->hThread, &cxt);
1278 | }
1279 | }
1280 | else {
1281 | if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget &&
1282 | cxt.DETOURS_EIP < (DETOURS_EIP_TYPE)((ULONG_PTR)o->pbTarget
1283 | + o->pTrampoline->cbRestore)
1284 | ) {
1285 |
1286 | cxt.DETOURS_EIP = (DETOURS_EIP_TYPE)
1287 | ((ULONG_PTR)o->pTrampoline
1288 | + detour_align_from_target(o->pTrampoline,
1289 | (BYTE)(cxt.DETOURS_EIP
1290 | - (DETOURS_EIP_TYPE)(ULONG_PTR)
1291 | o->pbTarget)));
1292 |
1293 | SetThreadContext(t->hThread, &cxt);
1294 | }
1295 | }
1296 | }
1297 | }
1298 | #undef DETOURS_EIP
1299 | }
1300 |
1301 | // Restore all of the page permissions and flush the icache.
1302 | HANDLE hProcess = GetCurrentProcess();
1303 | for (o = s_pPendingOperations; o != NULL;) {
1304 | // We don't care if this fails, because the code is still accessible.
1305 | DWORD dwOld;
1306 | VirtualProtect(o->pbTarget, o->pTrampoline->cbRestore, o->dwPerm, &dwOld);
1307 | FlushInstructionCache(hProcess, o->pbTarget, o->pTrampoline->cbRestore);
1308 |
1309 | if (o->fIsRemove && o->pTrampoline) {
1310 | detour_free_trampoline(o->pTrampoline);
1311 | o->pTrampoline = NULL;
1312 | freed = true;
1313 | }
1314 |
1315 | DetourOperation *n = o->pNext;
1316 | delete o;
1317 | o = n;
1318 | }
1319 | s_pPendingOperations = NULL;
1320 |
1321 | // Free any trampoline regions that are now unused.
1322 | if (freed && !s_fRetainRegions) {
1323 | detour_free_unused_trampoline_regions();
1324 | }
1325 |
1326 | // Make sure the trampoline pages are no longer writable.
1327 | detour_runnable_trampoline_regions();
1328 |
1329 | // Resume any suspended threads.
1330 | for (t = s_pPendingThreads; t != NULL;) {
1331 | // There is nothing we can do if this fails.
1332 | ResumeThread(t->hThread);
1333 |
1334 | DetourThread *n = t->pNext;
1335 | delete t;
1336 | t = n;
1337 | }
1338 | s_pPendingThreads = NULL;
1339 | s_nPendingThreadId = 0;
1340 |
1341 | if (pppFailedPointer != NULL) {
1342 | *pppFailedPointer = s_ppPendingError;
1343 | }
1344 |
1345 | return s_nPendingError;
1346 | }
1347 |
1348 | LONG WINAPI DetourUpdateThread(HANDLE hThread)
1349 | {
1350 | LONG error;
1351 |
1352 | // If any of the pending operations failed, then we don't need to do this.
1353 | if (s_nPendingError != NO_ERROR) {
1354 | return s_nPendingError;
1355 | }
1356 |
1357 | // Silently (and safely) drop any attempt to suspend our own thread.
1358 | if (hThread == GetCurrentThread()) {
1359 | return NO_ERROR;
1360 | }
1361 |
1362 | DetourThread *t = new DetourThread;
1363 | if (t == NULL) {
1364 | error = ERROR_NOT_ENOUGH_MEMORY;
1365 | fail:
1366 | if (t != NULL) {
1367 | delete t;
1368 | t = NULL;
1369 | }
1370 | s_nPendingError = error;
1371 | s_ppPendingError = NULL;
1372 | DETOUR_BREAK();
1373 | return error;
1374 | }
1375 |
1376 | if (SuspendThread(hThread) == (DWORD)-1) {
1377 | error = GetLastError();
1378 | DETOUR_BREAK();
1379 | goto fail;
1380 | }
1381 |
1382 | t->hThread = hThread;
1383 | t->pNext = s_pPendingThreads;
1384 | s_pPendingThreads = t;
1385 |
1386 | return NO_ERROR;
1387 | }
1388 |
1389 | ///////////////////////////////////////////////////////////// Transacted APIs.
1390 | //
1391 | LONG WINAPI DetourAttach(PVOID *ppPointer,
1392 | PVOID pDetour)
1393 | {
1394 | return DetourAttachEx(ppPointer, pDetour, NULL, NULL, NULL);
1395 | }
1396 |
1397 | LONG WINAPI DetourAttachEx(PVOID *ppPointer,
1398 | PVOID pDetour,
1399 | PDETOUR_TRAMPOLINE *ppRealTrampoline,
1400 | PVOID *ppRealTarget,
1401 | PVOID *ppRealDetour)
1402 | {
1403 | LONG error = NO_ERROR;
1404 |
1405 | if (ppRealTrampoline != NULL) {
1406 | *ppRealTrampoline = NULL;
1407 | }
1408 | if (ppRealTarget != NULL) {
1409 | *ppRealTarget = NULL;
1410 | }
1411 | if (ppRealDetour != NULL) {
1412 | *ppRealDetour = NULL;
1413 | }
1414 |
1415 | if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
1416 | DETOUR_TRACE(("transaction conflict with thread id=%d\n", s_nPendingThreadId));
1417 | return ERROR_INVALID_OPERATION;
1418 | }
1419 |
1420 | // If any of the pending operations failed, then we don't need to do this.
1421 | if (s_nPendingError != NO_ERROR) {
1422 | DETOUR_TRACE(("pending transaction error=%d\n", s_nPendingError));
1423 | return s_nPendingError;
1424 | }
1425 |
1426 | if (ppPointer == NULL) {
1427 | DETOUR_TRACE(("ppPointer is null\n"));
1428 | return ERROR_INVALID_HANDLE;
1429 | }
1430 | if (*ppPointer == NULL) {
1431 | error = ERROR_INVALID_HANDLE;
1432 | s_nPendingError = error;
1433 | s_ppPendingError = ppPointer;
1434 | DETOUR_TRACE(("*ppPointer is null (ppPointer=%p)\n", ppPointer));
1435 | DETOUR_BREAK();
1436 | return error;
1437 | }
1438 |
1439 | PBYTE pbTarget = (PBYTE)*ppPointer;
1440 | PDETOUR_TRAMPOLINE pTrampoline = NULL;
1441 | DetourOperation *o = NULL;
1442 |
1443 | #ifdef DETOURS_IA64
1444 | #error Feature not supported in this release.
1445 |
1446 |
1447 |
1448 |
1449 |
1450 |
1451 |
1452 |
1453 |
1454 |
1455 | #else // DETOURS_IA64
1456 | pbTarget = (PBYTE)DetourCodeFromPointer(pbTarget, NULL);
1457 | pDetour = DetourCodeFromPointer(pDetour, NULL);
1458 | #endif // !DETOURS_IA64
1459 |
1460 | // Don't follow a jump if its destination is the target function.
1461 | // This happens when the detour does nothing other than call the target.
1462 | if (pDetour == (PVOID)pbTarget) {
1463 | if (s_fIgnoreTooSmall) {
1464 | goto stop;
1465 | }
1466 | else {
1467 | DETOUR_BREAK();
1468 | goto fail;
1469 | }
1470 | }
1471 |
1472 | if (ppRealTarget != NULL) {
1473 | *ppRealTarget = pbTarget;
1474 | }
1475 | if (ppRealDetour != NULL) {
1476 | *ppRealDetour = pDetour;
1477 | }
1478 |
1479 | o = new DetourOperation;
1480 | if (o == NULL) {
1481 | error = ERROR_NOT_ENOUGH_MEMORY;
1482 | fail:
1483 | s_nPendingError = error;
1484 | DETOUR_BREAK();
1485 | stop:
1486 | if (pTrampoline != NULL) {
1487 | detour_free_trampoline(pTrampoline);
1488 | pTrampoline = NULL;
1489 | if (ppRealTrampoline != NULL) {
1490 | *ppRealTrampoline = NULL;
1491 | }
1492 | }
1493 | if (o != NULL) {
1494 | delete o;
1495 | o = NULL;
1496 | }
1497 | s_ppPendingError = ppPointer;
1498 | return error;
1499 | }
1500 |
1501 | pTrampoline = detour_alloc_trampoline(pbTarget);
1502 | if (pTrampoline == NULL) {
1503 | error = ERROR_NOT_ENOUGH_MEMORY;
1504 | DETOUR_BREAK();
1505 | goto fail;
1506 | }
1507 |
1508 | if (ppRealTrampoline != NULL) {
1509 | *ppRealTrampoline = pTrampoline;
1510 | }
1511 |
1512 | DETOUR_TRACE(("detours: pbTramp=%p, pDetour=%p\n", pTrampoline, pDetour));
1513 |
1514 | memset(pTrampoline->rAlign, 0, sizeof(pTrampoline->rAlign));
1515 |
1516 | // Determine the number of movable target instructions.
1517 | PBYTE pbSrc = pbTarget;
1518 | PBYTE pbTrampoline = pTrampoline->rbCode;
1519 | PBYTE pbPool = pbTrampoline + sizeof(pTrampoline->rbCode);
1520 | ULONG cbTarget = 0;
1521 | ULONG cbJump = SIZE_OF_JMP;
1522 | ULONG nAlign = 0;
1523 |
1524 | #ifdef DETOURS_ARM
1525 | #error Feature not supported in this release.
1526 |
1527 |
1528 |
1529 |
1530 |
1531 |
1532 |
1533 |
1534 |
1535 |
1536 |
1537 |
1538 |
1539 |
1540 |
1541 |
1542 |
1543 |
1544 |
1545 |
1546 |
1547 |
1548 |
1549 |
1550 |
1551 |
1552 | #endif
1553 |
1554 | while (cbTarget < cbJump) {
1555 | PBYTE pbOp = pbSrc;
1556 | LONG lExtra = 0;
1557 |
1558 | DETOUR_TRACE((" DetourCopyInstruction(%p,%p)\n",
1559 | pbTrampoline, pbSrc));
1560 | pbSrc = (PBYTE)
1561 | DetourCopyInstruction(pbTrampoline, (PVOID*)&pbPool, pbSrc, NULL, &lExtra);
1562 | DETOUR_TRACE((" DetourCopyInstruction() = %p (%d bytes)\n",
1563 | pbSrc, (int)(pbSrc - pbOp)));
1564 | pbTrampoline += (pbSrc - pbOp) + lExtra;
1565 | cbTarget = (LONG)(pbSrc - pbTarget);
1566 | pTrampoline->rAlign[nAlign].obTarget = cbTarget;
1567 | pTrampoline->rAlign[nAlign].obTrampoline = pbTrampoline - pTrampoline->rbCode;
1568 |
1569 | if (detour_does_code_end_function(pbOp)) {
1570 | break;
1571 | }
1572 | }
1573 |
1574 | // Consume, but don't duplicate padding if it is needed and available.
1575 | while (cbTarget < cbJump) {
1576 | LONG cFiller = detour_is_code_filler(pbSrc);
1577 | if (cFiller == 0) {
1578 | break;
1579 | }
1580 |
1581 | pbSrc += cFiller;
1582 | cbTarget = (LONG)(pbSrc - pbTarget);
1583 | }
1584 |
1585 | #if DETOUR_DEBUG
1586 | {
1587 | DETOUR_TRACE((" detours: rAlign ["));
1588 | LONG n = 0;
1589 | for (n = 0; n < ARRAYSIZE(pTrampoline->rAlign); n++) {
1590 | if (pTrampoline->rAlign[n].obTarget == 0 &&
1591 | pTrampoline->rAlign[n].obTrampoline == 0) {
1592 | break;
1593 | }
1594 | DETOUR_TRACE((" %d/%d",
1595 | pTrampoline->rAlign[n].obTarget,
1596 | pTrampoline->rAlign[n].obTrampoline
1597 | ));
1598 |
1599 | }
1600 | DETOUR_TRACE((" ]\n"));
1601 | }
1602 | #endif
1603 |
1604 | if (cbTarget < cbJump || nAlign > ARRAYSIZE(pTrampoline->rAlign)) {
1605 | // Too few instructions.
1606 |
1607 | error = ERROR_INVALID_BLOCK;
1608 | if (s_fIgnoreTooSmall) {
1609 | goto stop;
1610 | }
1611 | else {
1612 | DETOUR_BREAK();
1613 | goto fail;
1614 | }
1615 | }
1616 |
1617 | if (pbTrampoline > pbPool) {
1618 | __debugbreak();
1619 | }
1620 |
1621 | #if 0 // [GalenH]
1622 | if (cbTarget < pbTrampoline - pTrampoline->rbCode) {
1623 | __debugbreak();
1624 | }
1625 | #endif
1626 |
1627 | pTrampoline->cbCode = (BYTE)(pbTrampoline - pTrampoline->rbCode);
1628 | pTrampoline->cbRestore = (BYTE)cbTarget;
1629 | CopyMemory(pTrampoline->rbRestore, pbTarget, cbTarget);
1630 |
1631 | #if !defined(DETOURS_IA64)
1632 | if (cbTarget > sizeof(pTrampoline->rbCode) - cbJump) {
1633 | // Too many instructions.
1634 | error = ERROR_INVALID_HANDLE;
1635 | DETOUR_BREAK();
1636 | goto fail;
1637 | }
1638 | #endif // !DETOURS_IA64
1639 |
1640 | pTrampoline->pbRemain = pbTarget + cbTarget;
1641 | pTrampoline->pbDetour = (PBYTE)pDetour;
1642 |
1643 | #ifdef DETOURS_IA64
1644 | #error Feature not supported in this release.
1645 |
1646 |
1647 |
1648 |
1649 |
1650 |
1651 |
1652 |
1653 |
1654 |
1655 |
1656 |
1657 |
1658 |
1659 |
1660 |
1661 |
1662 |
1663 |
1664 |
1665 |
1666 |
1667 |
1668 |
1669 |
1670 |
1671 |
1672 |
1673 |
1674 |
1675 |
1676 |
1677 |
1678 |
1679 |
1680 |
1681 | #endif // DETOURS_IA64
1682 |
1683 | pbTrampoline = pTrampoline->rbCode + pTrampoline->cbCode;
1684 | #ifdef DETOURS_X64
1685 | #error Feature not supported in this release.
1686 |
1687 | #endif // DETOURS_X64
1688 |
1689 | #ifdef DETOURS_X86
1690 | pbTrampoline = detour_gen_jmp_immediate(pbTrampoline, pTrampoline->pbRemain);
1691 | pbTrampoline = detour_gen_brk(pbTrampoline, pbPool);
1692 | #endif // DETOURS_X86
1693 |
1694 | #ifdef DETOURS_ARM
1695 | #error Feature not supported in this release.
1696 |
1697 | #endif // DETOURS_ARM
1698 |
1699 | DWORD dwOld = 0;
1700 | if (!VirtualProtect(pbTarget, cbTarget, PAGE_EXECUTE_READWRITE, &dwOld)) {
1701 | error = GetLastError();
1702 | DETOUR_BREAK();
1703 | goto fail;
1704 | }
1705 |
1706 | DETOUR_TRACE(("detours: pbTarget=%p: "
1707 | "%02x %02x %02x %02x "
1708 | "%02x %02x %02x %02x "
1709 | "%02x %02x %02x %02x\n",
1710 | pbTarget,
1711 | pbTarget[0], pbTarget[1], pbTarget[2], pbTarget[3],
1712 | pbTarget[4], pbTarget[5], pbTarget[6], pbTarget[7],
1713 | pbTarget[8], pbTarget[9], pbTarget[10], pbTarget[11]));
1714 | DETOUR_TRACE(("detours: pbTramp =%p: "
1715 | "%02x %02x %02x %02x "
1716 | "%02x %02x %02x %02x "
1717 | "%02x %02x %02x %02x\n",
1718 | pTrampoline,
1719 | pTrampoline->rbCode[0], pTrampoline->rbCode[1],
1720 | pTrampoline->rbCode[2], pTrampoline->rbCode[3],
1721 | pTrampoline->rbCode[4], pTrampoline->rbCode[5],
1722 | pTrampoline->rbCode[6], pTrampoline->rbCode[7],
1723 | pTrampoline->rbCode[8], pTrampoline->rbCode[9],
1724 | pTrampoline->rbCode[10], pTrampoline->rbCode[11]));
1725 |
1726 | o->fIsRemove = FALSE;
1727 | o->ppbPointer = (PBYTE*)ppPointer;
1728 | o->pTrampoline = pTrampoline;
1729 | o->pbTarget = pbTarget;
1730 | o->dwPerm = dwOld;
1731 | o->pNext = s_pPendingOperations;
1732 | s_pPendingOperations = o;
1733 |
1734 | return NO_ERROR;
1735 | }
1736 |
1737 | LONG WINAPI DetourDetach(PVOID *ppPointer,
1738 | PVOID pDetour)
1739 | {
1740 | LONG error = NO_ERROR;
1741 |
1742 | if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
1743 | return ERROR_INVALID_OPERATION;
1744 | }
1745 |
1746 | // If any of the pending operations failed, then we don't need to do this.
1747 | if (s_nPendingError != NO_ERROR) {
1748 | return s_nPendingError;
1749 | }
1750 |
1751 | if (ppPointer == NULL) {
1752 | return ERROR_INVALID_HANDLE;
1753 | }
1754 | if (*ppPointer == NULL) {
1755 | error = ERROR_INVALID_HANDLE;
1756 | s_nPendingError = error;
1757 | s_ppPendingError = ppPointer;
1758 | DETOUR_BREAK();
1759 | return error;
1760 | }
1761 |
1762 | DetourOperation *o = new DetourOperation;
1763 | if (o == NULL) {
1764 | error = ERROR_NOT_ENOUGH_MEMORY;
1765 | fail:
1766 | s_nPendingError = error;
1767 | DETOUR_BREAK();
1768 | stop:
1769 | if (o != NULL) {
1770 | delete o;
1771 | o = NULL;
1772 | }
1773 | s_ppPendingError = ppPointer;
1774 | return error;
1775 | }
1776 |
1777 |
1778 | #ifdef DETOURS_IA64
1779 | #error Feature not supported in this release.
1780 |
1781 |
1782 |
1783 |
1784 |
1785 |
1786 |
1787 |
1788 |
1789 |
1790 |
1791 |
1792 |
1793 |
1794 |
1795 |
1796 |
1797 |
1798 |
1799 |
1800 |
1801 |
1802 |
1803 |
1804 |
1805 |
1806 |
1807 |
1808 |
1809 |
1810 |
1811 |
1812 |
1813 |
1814 |
1815 |
1816 |
1817 |
1818 |
1819 |
1820 |
1821 |
1822 | #else // !DETOURS_IA64
1823 | PDETOUR_TRAMPOLINE pTrampoline =
1824 | (PDETOUR_TRAMPOLINE)DetourCodeFromPointer(*ppPointer, NULL);
1825 | pDetour = DetourCodeFromPointer(pDetour, NULL);
1826 | #endif // !DETOURS_IA64
1827 |
1828 | ////////////////////////////////////// Verify that Trampoline is in place.
1829 | //
1830 | LONG cbTarget = pTrampoline->cbRestore;
1831 | PBYTE pbTarget = pTrampoline->pbRemain - cbTarget;
1832 | if (cbTarget == 0 || cbTarget > sizeof(pTrampoline->rbCode)) {
1833 | error = ERROR_INVALID_BLOCK;
1834 | if (s_fIgnoreTooSmall) {
1835 | goto stop;
1836 | }
1837 | else {
1838 | DETOUR_BREAK();
1839 | goto fail;
1840 | }
1841 | }
1842 |
1843 | if (pTrampoline->pbDetour != pDetour) {
1844 | error = ERROR_INVALID_BLOCK;
1845 | if (s_fIgnoreTooSmall) {
1846 | goto stop;
1847 | }
1848 | else {
1849 | DETOUR_BREAK();
1850 | goto fail;
1851 | }
1852 | }
1853 |
1854 | DWORD dwOld = 0;
1855 | if (!VirtualProtect(pbTarget, cbTarget,
1856 | PAGE_EXECUTE_READWRITE, &dwOld)) {
1857 | error = GetLastError();
1858 | DETOUR_BREAK();
1859 | goto fail;
1860 | }
1861 |
1862 | o->fIsRemove = TRUE;
1863 | o->ppbPointer = (PBYTE*)ppPointer;
1864 | o->pTrampoline = pTrampoline;
1865 | o->pbTarget = pbTarget;
1866 | o->dwPerm = dwOld;
1867 | o->pNext = s_pPendingOperations;
1868 | s_pPendingOperations = o;
1869 |
1870 | return NO_ERROR;
1871 | }
1872 |
1873 | // End of File
1874 |
--------------------------------------------------------------------------------
/src/SuperF12.dll/Detours/disasm.cpp:
--------------------------------------------------------------------------------
1 | //////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Detours Disassembler (disasm.cpp of detours.lib)
4 | //
5 | // Microsoft Research Detours Package, Version 3.0 Build_316.
6 | //
7 | // Copyright (c) Microsoft Corporation. All rights reserved.
8 | //
9 |
10 | #include
11 | #include
12 |
13 | // #define DETOUR_DEBUG 1
14 | #define DETOURS_INTERNAL
15 |
16 | #include "detours.h"
17 |
18 | #if defined(DETOURS_X86)
19 | #elif defined(DETOURS_X64)
20 | #elif defined(DETOURS_IA64)
21 | #elif defined(DETOURS_ARM)
22 | #else
23 | #error Must define one of DETOURS_X86, DETOURS_X64, DETOURS_IA64, or DETOURS_ARM
24 | #endif
25 |
26 | #undef ASSERT
27 | #define ASSERT(x)
28 |
29 | //////////////////////////////////////////////////////////////////////////////
30 | //
31 | // Function:
32 | // DetourCopyInstruction(PVOID pDst,
33 | // PVOID *ppDstPool
34 | // PVOID pSrc,
35 | // PVOID *ppTarget,
36 | // LONG *plExtra)
37 | // Purpose:
38 | // Copy a single instruction from pSrc to pDst.
39 | //
40 | // Arguments:
41 | // pDst:
42 | // Destination address for the instruction. May be NULL in which
43 | // case DetourCopyInstruction is used to measure an instruction.
44 | // If not NULL then the source instruction is copied to the
45 | // destination instruction and any relative arguments are adjusted.
46 | // ppDstPool:
47 | // Destination address for the end of the constant pool. The
48 | // constant pool works backwards toward pDst. All memory between
49 | // pDst and *ppDstPool must be available for use by this function.
50 | // ppDstPool may be NULL if pDst is NULL.
51 | // pSrc:
52 | // Source address of the instruction.
53 | // ppTarget:
54 | // Out parameter for any target instruction address pointed to by
55 | // the instruction. For example, a branch or a jump insruction has
56 | // a target, but a load or store instruction doesn't. A target is
57 | // another instruction that may be executed as a result of this
58 | // instruction. ppTarget may be NULL.
59 | // plExtra:
60 | // Out parameter for the number of extra bytes needed by the
61 | // instruction to reach the target. For example, lExtra = 3 if the
62 | // instruction had an 8-bit relative offset, but needs a 32-bit
63 | // relative offset.
64 | //
65 | // Returns:
66 | // Returns the address of the next instruction (following in the source)
67 | // instruction. By subtracting pSrc from the return value, the caller
68 | // can determinte the size of the instruction copied.
69 | //
70 | // Comments:
71 | // By following the pTarget, the caller can follow alternate
72 | // instruction streams. However, it is not always possible to determine
73 | // the target based on static analysis. For example, the destination of
74 | // a jump relative to a register cannot be determined from just the
75 | // instruction stream. The output value, pTarget, can have any of the
76 | // following outputs:
77 | // DETOUR_INSTRUCTION_TARGET_NONE:
78 | // The instruction has no targets.
79 | // DETOUR_INSTRUCTION_TARGET_DYNAMIC:
80 | // The instruction has a non-deterministic (dynamic) target.
81 | // (i.e. the jump is to an address held in a register.)
82 | // Address: The instruction has the specified target.
83 | //
84 | // When copying instructions, DetourCopyInstruction insures that any
85 | // targets remain constant. It does so by adjusting any IP relative
86 | // offsets.
87 | //
88 |
89 | //////////////////////////////////////////////////// X86 and X64 Disassembler.
90 | //
91 | // Includes full support for all x86 chips prior to the Pentium III.
92 | //
93 | #if defined(DETOURS_X64) || defined(DETOURS_X86)
94 |
95 | class CDetourDis
96 | {
97 | public:
98 | CDetourDis(PBYTE *ppbTarget, LONG *plExtra);
99 |
100 | PBYTE CopyInstruction(PBYTE pbDst, PBYTE pbSrc);
101 | static BOOL SanityCheckSystem();
102 |
103 | public:
104 | struct COPYENTRY;
105 | typedef const COPYENTRY * REFCOPYENTRY;
106 |
107 | typedef PBYTE (CDetourDis::* COPYFUNC)(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
108 |
109 | enum {
110 | DYNAMIC = 0x1u,
111 | ADDRESS = 0x2u,
112 | NOENLARGE = 0x4u,
113 | RAX = 0x8u,
114 |
115 | SIB = 0x10u,
116 | RIP = 0x20u,
117 | NOTSIB = 0x0fu,
118 | };
119 | struct COPYENTRY
120 | {
121 | ULONG nOpcode : 8; // Opcode
122 | ULONG nFixedSize : 4; // Fixed size of opcode
123 | ULONG nFixedSize16 : 4; // Fixed size when 16 bit operand
124 | ULONG nModOffset : 4; // Offset to mod/rm byte (0=none)
125 | LONG nRelOffset : 4; // Offset to relative target.
126 | LONG nTargetBack : 4; // Offset back to absolute or rip target
127 | ULONG nFlagBits : 4; // Flags for DYNAMIC, etc.
128 | COPYFUNC pfCopy; // Function pointer.
129 | };
130 |
131 | protected:
132 | // These macros define common uses of nFixedSize..pfCopy.
133 | #define ENTRY_CopyBytes1 1, 1, 0, 0, 0, 0, &CDetourDis::CopyBytes
134 | #define ENTRY_CopyBytes1Dynamic 1, 1, 0, 0, 0, DYNAMIC, &CDetourDis::CopyBytes
135 | #define ENTRY_CopyBytes2 2, 2, 0, 0, 0, 0, &CDetourDis::CopyBytes
136 | #define ENTRY_CopyBytes2Jump 2, 2, 0, 1, 0, 0, &CDetourDis::CopyBytesJump
137 | #define ENTRY_CopyBytes2CantJump 2, 2, 0, 1, 0, NOENLARGE, &CDetourDis::CopyBytes
138 | #define ENTRY_CopyBytes2Dynamic 2, 2, 0, 0, 0, DYNAMIC, &CDetourDis::CopyBytes
139 | #define ENTRY_CopyBytes3 3, 3, 0, 0, 0, 0, &CDetourDis::CopyBytes
140 | #define ENTRY_CopyBytes3Dynamic 3, 3, 0, 0, 0, DYNAMIC, &CDetourDis::CopyBytes
141 | #define ENTRY_CopyBytes3Or5 5, 3, 0, 0, 0, 0, &CDetourDis::CopyBytes
142 | #define ENTRY_CopyBytes3Or5Rax 5, 3, 0, 0, 0, RAX, &CDetourDis::CopyBytes
143 | #define ENTRY_CopyBytes3Or5Target 5, 3, 0, 1, 0, 0, &CDetourDis::CopyBytes
144 | #define ENTRY_CopyBytes5Or7Dynamic 7, 5, 0, 0, 0, DYNAMIC, &CDetourDis::CopyBytes
145 | #define ENTRY_CopyBytes3Or5Address 5, 3, 0, 0, 0, ADDRESS, &CDetourDis::CopyBytes
146 | #define ENTRY_CopyBytes4 4, 4, 0, 0, 0, 0, &CDetourDis::CopyBytes
147 | #define ENTRY_CopyBytes5 5, 5, 0, 0, 0, 0, &CDetourDis::CopyBytes
148 | #define ENTRY_CopyBytes7 7, 7, 0, 0, 0, 0, &CDetourDis::CopyBytes
149 | #define ENTRY_CopyBytes2Mod 2, 2, 1, 0, 0, 0, &CDetourDis::CopyBytes
150 | #define ENTRY_CopyBytes2Mod1 3, 3, 1, 0, 1, 0, &CDetourDis::CopyBytes
151 | #define ENTRY_CopyBytes2ModOperand 6, 4, 1, 0, 4, 0, &CDetourDis::CopyBytes
152 | #define ENTRY_CopyBytes3Mod 3, 3, 2, 0, 0, 0, &CDetourDis::CopyBytes
153 | #define ENTRY_CopyBytesPrefix 1, 1, 0, 0, 0, 0, &CDetourDis::CopyBytesPrefix
154 | #define ENTRY_CopyBytesRax 1, 1, 0, 0, 0, 0, &CDetourDis::CopyBytesRax
155 | #define ENTRY_Copy0F 1, 1, 0, 0, 0, 0, &CDetourDis::Copy0F
156 | #define ENTRY_Copy66 1, 1, 0, 0, 0, 0, &CDetourDis::Copy66
157 | #define ENTRY_Copy67 1, 1, 0, 0, 0, 0, &CDetourDis::Copy67
158 | #define ENTRY_CopyF6 0, 0, 0, 0, 0, 0, &CDetourDis::CopyF6
159 | #define ENTRY_CopyF7 0, 0, 0, 0, 0, 0, &CDetourDis::CopyF7
160 | #define ENTRY_CopyFF 0, 0, 0, 0, 0, 0, &CDetourDis::CopyFF
161 | #define ENTRY_Invalid 1, 1, 0, 0, 0, 0, &CDetourDis::Invalid
162 | #define ENTRY_End 0, 0, 0, 0, 0, 0, NULL
163 |
164 | PBYTE CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
165 | PBYTE CopyBytesPrefix(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
166 | PBYTE CopyBytesRax(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
167 | PBYTE CopyBytesJump(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
168 |
169 | PBYTE Invalid(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
170 |
171 | PBYTE AdjustTarget(PBYTE pbDst, PBYTE pbSrc, LONG cbOp,
172 | LONG cbTargetOffset, LONG cbTargetSize);
173 |
174 | protected:
175 | PBYTE Copy0F(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
176 | PBYTE Copy66(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
177 | PBYTE Copy67(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
178 | PBYTE CopyF6(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
179 | PBYTE CopyF7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
180 | PBYTE CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc);
181 |
182 | protected:
183 | static const COPYENTRY s_rceCopyTable[257];
184 | static const COPYENTRY s_rceCopyTable0F[257];
185 | static const BYTE s_rbModRm[256];
186 |
187 | protected:
188 | BOOL m_bOperandOverride;
189 | BOOL m_bAddressOverride;
190 | BOOL m_bRaxOverride;
191 |
192 | PBYTE * m_ppbTarget;
193 | LONG * m_plExtra;
194 |
195 | LONG m_lScratchExtra;
196 | PBYTE m_pbScratchTarget;
197 | BYTE m_rbScratchDst[64];
198 | };
199 |
200 | PVOID WINAPI DetourCopyInstruction(PVOID pDst,
201 | PVOID *ppDstPool,
202 | PVOID pSrc,
203 | PVOID *ppTarget,
204 | LONG *plExtra)
205 | {
206 | (void)ppDstPool; // x86 & x64 don't use a constant pool.
207 | CDetourDis oDetourDisasm((PBYTE*)ppTarget, plExtra);
208 | return oDetourDisasm.CopyInstruction((PBYTE)pDst, (PBYTE)pSrc);
209 | }
210 |
211 | /////////////////////////////////////////////////////////// Disassembler Code.
212 | //
213 | CDetourDis::CDetourDis(PBYTE *ppbTarget, LONG *plExtra)
214 | {
215 | m_bOperandOverride = FALSE;
216 | m_bAddressOverride = FALSE;
217 | m_bRaxOverride = FALSE;
218 |
219 | m_ppbTarget = ppbTarget ? ppbTarget : &m_pbScratchTarget;
220 | m_plExtra = plExtra ? plExtra : &m_lScratchExtra;
221 |
222 | *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_NONE;
223 | *m_plExtra = 0;
224 | }
225 |
226 | PBYTE CDetourDis::CopyInstruction(PBYTE pbDst, PBYTE pbSrc)
227 | {
228 | // Configure scratch areas if real areas are not available.
229 | if (NULL == pbDst) {
230 | pbDst = m_rbScratchDst;
231 | }
232 | if (NULL == pbSrc) {
233 | // We can't copy a non-existent instruction.
234 | SetLastError(ERROR_INVALID_DATA);
235 | return NULL;
236 | }
237 |
238 | // Figure out how big the instruction is, do the appropriate copy,
239 | // and figure out what the target of the instruction is if any.
240 | //
241 | REFCOPYENTRY pEntry = &s_rceCopyTable[pbSrc[0]];
242 | return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
243 | }
244 |
245 | PBYTE CDetourDis::CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
246 | {
247 | #ifdef DETOURS_X64
248 | #error Feature not supported in this release.
249 |
250 |
251 |
252 |
253 | #else
254 | LONG nBytesFixed = (pEntry->nFlagBits & ADDRESS)
255 | ? (m_bAddressOverride ? pEntry->nFixedSize16 : pEntry->nFixedSize)
256 | : (m_bOperandOverride ? pEntry->nFixedSize16 : pEntry->nFixedSize);
257 | #endif
258 |
259 | LONG nBytes = nBytesFixed;
260 | LONG nRelOffset = pEntry->nRelOffset;
261 | LONG cbTarget = nBytes - nRelOffset;
262 | if (pEntry->nModOffset > 0) {
263 | BYTE bModRm = pbSrc[pEntry->nModOffset];
264 | BYTE bFlags = s_rbModRm[bModRm];
265 |
266 | nBytes += bFlags & NOTSIB;
267 |
268 | if (bFlags & SIB) {
269 | BYTE bSib = pbSrc[pEntry->nModOffset + 1];
270 |
271 | if ((bSib & 0x07) == 0x05) {
272 | if ((bModRm & 0xc0) == 0x00) {
273 | nBytes += 4;
274 | }
275 | else if ((bModRm & 0xc0) == 0x40) {
276 | nBytes += 1;
277 | }
278 | else if ((bModRm & 0xc0) == 0x80) {
279 | nBytes += 4;
280 | }
281 | }
282 | cbTarget = nBytes - nRelOffset;
283 | }
284 | else if (bFlags & RIP) {
285 | #ifdef DETOURS_X64
286 | #error Feature not supported in this release.
287 |
288 |
289 | #endif
290 | }
291 | }
292 | CopyMemory(pbDst, pbSrc, nBytes);
293 |
294 | if (nRelOffset) {
295 | *m_ppbTarget = AdjustTarget(pbDst, pbSrc, nBytesFixed, nRelOffset, cbTarget);
296 | #ifdef DETOURS_X64
297 | #error Feature not supported in this release.
298 |
299 |
300 |
301 | #endif
302 | }
303 | if (pEntry->nFlagBits & NOENLARGE) {
304 | *m_plExtra = -*m_plExtra;
305 | }
306 | if (pEntry->nFlagBits & DYNAMIC) {
307 | *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
308 | }
309 | return pbSrc + nBytes;
310 | }
311 |
312 | PBYTE CDetourDis::CopyBytesPrefix(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
313 | {
314 | CopyBytes(pEntry, pbDst, pbSrc);
315 |
316 | pEntry = &s_rceCopyTable[pbSrc[1]];
317 | return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1);
318 | }
319 |
320 | PBYTE CDetourDis::CopyBytesRax(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
321 | {
322 | CopyBytes(pEntry, pbDst, pbSrc);
323 |
324 | if (*pbSrc & 0x8) {
325 | m_bRaxOverride = TRUE;
326 | }
327 |
328 | pEntry = &s_rceCopyTable[pbSrc[1]];
329 | return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1);
330 | }
331 |
332 | PBYTE CDetourDis::CopyBytesJump(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
333 | {
334 | (void)pEntry;
335 |
336 | PVOID pvSrcAddr = &pbSrc[1];
337 | PVOID pvDstAddr = NULL;
338 | LONG_PTR nOldOffset = (LONG_PTR)*(CHAR*&)pvSrcAddr;
339 | LONG_PTR nNewOffset = 0;
340 |
341 | *m_ppbTarget = pbSrc + 2 + nOldOffset;
342 |
343 | if (pbSrc[0] == 0xeb) {
344 | pbDst[0] = 0xe9;
345 | pvDstAddr = &pbDst[1];
346 | nNewOffset = nOldOffset - ((pbDst - pbSrc) + 3);
347 | *(LONG*&)pvDstAddr = (LONG)nNewOffset;
348 |
349 | *m_plExtra = 3;
350 | return pbSrc + 2;
351 | }
352 |
353 | ASSERT(pbSrc[0] >= 0x70 && pbSrc[0] <= 0x7f);
354 |
355 | pbDst[0] = 0x0f;
356 | pbDst[1] = 0x80 | (pbSrc[0] & 0xf);
357 | pvDstAddr = &pbDst[2];
358 | nNewOffset = nOldOffset - ((pbDst - pbSrc) + 4);
359 | *(LONG*&)pvDstAddr = (LONG)nNewOffset;
360 |
361 | *m_plExtra = 4;
362 | return pbSrc + 2;
363 | }
364 |
365 | PBYTE CDetourDis::AdjustTarget(PBYTE pbDst, PBYTE pbSrc, LONG cbOp,
366 | LONG cbTargetOffset, LONG cbTargetSize)
367 | {
368 | PBYTE pbTarget = NULL;
369 | PVOID pvTargetAddr = &pbDst[cbTargetOffset];
370 | LONG_PTR nOldOffset = 0;
371 |
372 | switch (cbTargetSize) {
373 | case 1:
374 | nOldOffset = (LONG_PTR)*(CHAR*&)pvTargetAddr;
375 | break;
376 | case 2:
377 | nOldOffset = (LONG_PTR)*(SHORT*&)pvTargetAddr;
378 | break;
379 | case 4:
380 | nOldOffset = (LONG_PTR)*(LONG*&)pvTargetAddr;
381 | break;
382 | case 8:
383 | nOldOffset = (LONG_PTR)*(LONG_PTR*&)pvTargetAddr;
384 | break;
385 | default:
386 | ASSERT(!"cbTargetSize is invalid.");
387 | break;
388 | }
389 |
390 | pbTarget = pbSrc + cbOp + nOldOffset;
391 | LONG_PTR nNewOffset = nOldOffset - (pbDst - pbSrc);
392 |
393 | switch (cbTargetSize) {
394 | case 1:
395 | *(CHAR*&)pvTargetAddr = (CHAR)nNewOffset;
396 | if (nNewOffset < SCHAR_MIN || nNewOffset > SCHAR_MAX) {
397 | *m_plExtra = sizeof(ULONG) - 1;
398 | }
399 | break;
400 | case 2:
401 | *(SHORT*&)pvTargetAddr = (SHORT)nNewOffset;
402 | if (nNewOffset < SHRT_MIN || nNewOffset > SHRT_MAX) {
403 | *m_plExtra = sizeof(ULONG) - 2;
404 | }
405 | break;
406 | case 4:
407 | *(LONG*&)pvTargetAddr = (LONG)nNewOffset;
408 | if (nNewOffset < LONG_MIN || nNewOffset > LONG_MAX) {
409 | *m_plExtra = sizeof(ULONG) - 4;
410 | }
411 | break;
412 | case 8:
413 | *(LONG_PTR*&)pvTargetAddr = (LONG_PTR)nNewOffset;
414 | break;
415 | }
416 | ASSERT(pbDst + cbOp + nNewOffset == pbTarget);
417 | return pbTarget;
418 | }
419 |
420 | PBYTE CDetourDis::Invalid(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
421 | {
422 | (void)pbDst;
423 | (void)pEntry;
424 | ASSERT(!"Invalid Instruction");
425 | return pbSrc + 1;
426 | }
427 |
428 | ////////////////////////////////////////////////////// Individual Bytes Codes.
429 | //
430 | PBYTE CDetourDis::Copy0F(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
431 | {
432 | CopyBytes(pEntry, pbDst, pbSrc);
433 |
434 | pEntry = &s_rceCopyTable0F[pbSrc[1]];
435 | return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1);
436 | }
437 |
438 | PBYTE CDetourDis::Copy66(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
439 | { // Operand-size override prefix
440 | m_bOperandOverride = TRUE;
441 | return CopyBytesPrefix(pEntry, pbDst, pbSrc);
442 | }
443 |
444 | PBYTE CDetourDis::Copy67(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
445 | { // Address size override prefix
446 | m_bAddressOverride = TRUE;
447 | return CopyBytesPrefix(pEntry, pbDst, pbSrc);
448 | }
449 |
450 | PBYTE CDetourDis::CopyF6(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
451 | {
452 | (void)pEntry;
453 |
454 | // TEST BYTE /0
455 | if (0x00 == (0x38 & pbSrc[1])) { // reg(bits 543) of ModR/M == 0
456 | const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod1 };
457 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
458 | }
459 | // DIV /6
460 | // IDIV /7
461 | // IMUL /5
462 | // MUL /4
463 | // NEG /3
464 | // NOT /2
465 |
466 | const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod };
467 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
468 | }
469 |
470 | PBYTE CDetourDis::CopyF7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
471 | {
472 | (void)pEntry;
473 |
474 | // TEST WORD /0
475 | if (0x00 == (0x38 & pbSrc[1])) { // reg(bits 543) of ModR/M == 0
476 | const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2ModOperand };
477 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
478 | }
479 |
480 | // DIV /6
481 | // IDIV /7
482 | // IMUL /5
483 | // MUL /4
484 | // NEG /3
485 | // NOT /2
486 | const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2Mod };
487 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
488 | }
489 |
490 | PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
491 | { // CALL /2
492 | // CALL /3
493 | // INC /0
494 | // JMP /4
495 | // JMP /5
496 | // PUSH /6
497 | (void)pEntry;
498 |
499 | if (0x15 == pbSrc[1] || 0x25 == pbSrc[1]) { // CALL [], JMP []
500 | #ifdef DETOURS_X64
501 | #error Feature not supported in this release.
502 |
503 |
504 | #else
505 | PBYTE *ppbTarget = *(PBYTE**)&pbSrc[2];
506 | *m_ppbTarget = *ppbTarget;
507 | #endif
508 | }
509 | else if (0x10 == (0x38 & pbSrc[1]) || // CALL /2 --> reg(bits 543) of ModR/M == 010
510 | 0x18 == (0x38 & pbSrc[1]) || // CALL /3 --> reg(bits 543) of ModR/M == 011
511 | 0x20 == (0x38 & pbSrc[1]) || // JMP /4 --> reg(bits 543) of ModR/M == 100
512 | 0x28 == (0x38 & pbSrc[1]) // JMP /5 --> reg(bits 543) of ModR/M == 101
513 | ) {
514 | *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC;
515 | }
516 | const COPYENTRY ce = { 0xff, ENTRY_CopyBytes2Mod };
517 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
518 | }
519 |
520 | ///////////////////////////////////////////////////////// Disassembler Tables.
521 | //
522 | const BYTE CDetourDis::s_rbModRm[256] = {
523 | 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 0x
524 | 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 1x
525 | 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 2x
526 | 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 3x
527 | 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 4x
528 | 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 5x
529 | 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 6x
530 | 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 7x
531 | 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // 8x
532 | 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // 9x
533 | 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // Ax
534 | 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // Bx
535 | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Cx
536 | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Dx
537 | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Ex
538 | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 // Fx
539 | };
540 |
541 | const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[257] =
542 | {
543 | { 0x00, ENTRY_CopyBytes2Mod }, // ADD /r
544 | { 0x01, ENTRY_CopyBytes2Mod }, // ADD /r
545 | { 0x02, ENTRY_CopyBytes2Mod }, // ADD /r
546 | { 0x03, ENTRY_CopyBytes2Mod }, // ADD /r
547 | { 0x04, ENTRY_CopyBytes2 }, // ADD ib
548 | { 0x05, ENTRY_CopyBytes3Or5 }, // ADD iw
549 | { 0x06, ENTRY_CopyBytes1 }, // PUSH
550 | { 0x07, ENTRY_CopyBytes1 }, // POP
551 | { 0x08, ENTRY_CopyBytes2Mod }, // OR /r
552 | { 0x09, ENTRY_CopyBytes2Mod }, // OR /r
553 | { 0x0A, ENTRY_CopyBytes2Mod }, // OR /r
554 | { 0x0B, ENTRY_CopyBytes2Mod }, // OR /r
555 | { 0x0C, ENTRY_CopyBytes2 }, // OR ib
556 | { 0x0D, ENTRY_CopyBytes3Or5 }, // OR iw
557 | { 0x0E, ENTRY_CopyBytes1 }, // PUSH
558 | { 0x0F, ENTRY_Copy0F }, // Extension Ops
559 | { 0x10, ENTRY_CopyBytes2Mod }, // ADC /r
560 | { 0x11, ENTRY_CopyBytes2Mod }, // ADC /r
561 | { 0x12, ENTRY_CopyBytes2Mod }, // ADC /r
562 | { 0x13, ENTRY_CopyBytes2Mod }, // ADC /r
563 | { 0x14, ENTRY_CopyBytes2 }, // ADC ib
564 | { 0x15, ENTRY_CopyBytes3Or5 }, // ADC id
565 | { 0x16, ENTRY_CopyBytes1 }, // PUSH
566 | { 0x17, ENTRY_CopyBytes1 }, // POP
567 | { 0x18, ENTRY_CopyBytes2Mod }, // SBB /r
568 | { 0x19, ENTRY_CopyBytes2Mod }, // SBB /r
569 | { 0x1A, ENTRY_CopyBytes2Mod }, // SBB /r
570 | { 0x1B, ENTRY_CopyBytes2Mod }, // SBB /r
571 | { 0x1C, ENTRY_CopyBytes2 }, // SBB ib
572 | { 0x1D, ENTRY_CopyBytes3Or5 }, // SBB id
573 | { 0x1E, ENTRY_CopyBytes1 }, // PUSH
574 | { 0x1F, ENTRY_CopyBytes1 }, // POP
575 | { 0x20, ENTRY_CopyBytes2Mod }, // AND /r
576 | { 0x21, ENTRY_CopyBytes2Mod }, // AND /r
577 | { 0x22, ENTRY_CopyBytes2Mod }, // AND /r
578 | { 0x23, ENTRY_CopyBytes2Mod }, // AND /r
579 | { 0x24, ENTRY_CopyBytes2 }, // AND ib
580 | { 0x25, ENTRY_CopyBytes3Or5 }, // AND id
581 | { 0x26, ENTRY_CopyBytesPrefix }, // ES prefix
582 | { 0x27, ENTRY_CopyBytes1 }, // DAA
583 | { 0x28, ENTRY_CopyBytes2Mod }, // SUB /r
584 | { 0x29, ENTRY_CopyBytes2Mod }, // SUB /r
585 | { 0x2A, ENTRY_CopyBytes2Mod }, // SUB /r
586 | { 0x2B, ENTRY_CopyBytes2Mod }, // SUB /r
587 | { 0x2C, ENTRY_CopyBytes2 }, // SUB ib
588 | { 0x2D, ENTRY_CopyBytes3Or5 }, // SUB id
589 | { 0x2E, ENTRY_CopyBytesPrefix }, // CS prefix
590 | { 0x2F, ENTRY_CopyBytes1 }, // DAS
591 | { 0x30, ENTRY_CopyBytes2Mod }, // XOR /r
592 | { 0x31, ENTRY_CopyBytes2Mod }, // XOR /r
593 | { 0x32, ENTRY_CopyBytes2Mod }, // XOR /r
594 | { 0x33, ENTRY_CopyBytes2Mod }, // XOR /r
595 | { 0x34, ENTRY_CopyBytes2 }, // XOR ib
596 | { 0x35, ENTRY_CopyBytes3Or5 }, // XOR id
597 | { 0x36, ENTRY_CopyBytesPrefix }, // SS prefix
598 | { 0x37, ENTRY_CopyBytes1 }, // AAA
599 | { 0x38, ENTRY_CopyBytes2Mod }, // CMP /r
600 | { 0x39, ENTRY_CopyBytes2Mod }, // CMP /r
601 | { 0x3A, ENTRY_CopyBytes2Mod }, // CMP /r
602 | { 0x3B, ENTRY_CopyBytes2Mod }, // CMP /r
603 | { 0x3C, ENTRY_CopyBytes2 }, // CMP ib
604 | { 0x3D, ENTRY_CopyBytes3Or5 }, // CMP id
605 | { 0x3E, ENTRY_CopyBytesPrefix }, // DS prefix
606 | { 0x3F, ENTRY_CopyBytes1 }, // AAS
607 | #ifdef DETOURS_X64 // For Rax Prefix
608 | #error Feature not supported in this release.
609 |
610 |
611 |
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
621 |
622 |
623 |
624 | #else
625 | { 0x40, ENTRY_CopyBytes1 }, // INC
626 | { 0x41, ENTRY_CopyBytes1 }, // INC
627 | { 0x42, ENTRY_CopyBytes1 }, // INC
628 | { 0x43, ENTRY_CopyBytes1 }, // INC
629 | { 0x44, ENTRY_CopyBytes1 }, // INC
630 | { 0x45, ENTRY_CopyBytes1 }, // INC
631 | { 0x46, ENTRY_CopyBytes1 }, // INC
632 | { 0x47, ENTRY_CopyBytes1 }, // INC
633 | { 0x48, ENTRY_CopyBytes1 }, // DEC
634 | { 0x49, ENTRY_CopyBytes1 }, // DEC
635 | { 0x4A, ENTRY_CopyBytes1 }, // DEC
636 | { 0x4B, ENTRY_CopyBytes1 }, // DEC
637 | { 0x4C, ENTRY_CopyBytes1 }, // DEC
638 | { 0x4D, ENTRY_CopyBytes1 }, // DEC
639 | { 0x4E, ENTRY_CopyBytes1 }, // DEC
640 | { 0x4F, ENTRY_CopyBytes1 }, // DEC
641 | #endif
642 | { 0x50, ENTRY_CopyBytes1 }, // PUSH
643 | { 0x51, ENTRY_CopyBytes1 }, // PUSH
644 | { 0x52, ENTRY_CopyBytes1 }, // PUSH
645 | { 0x53, ENTRY_CopyBytes1 }, // PUSH
646 | { 0x54, ENTRY_CopyBytes1 }, // PUSH
647 | { 0x55, ENTRY_CopyBytes1 }, // PUSH
648 | { 0x56, ENTRY_CopyBytes1 }, // PUSH
649 | { 0x57, ENTRY_CopyBytes1 }, // PUSH
650 | { 0x58, ENTRY_CopyBytes1 }, // POP
651 | { 0x59, ENTRY_CopyBytes1 }, // POP
652 | { 0x5A, ENTRY_CopyBytes1 }, // POP
653 | { 0x5B, ENTRY_CopyBytes1 }, // POP
654 | { 0x5C, ENTRY_CopyBytes1 }, // POP
655 | { 0x5D, ENTRY_CopyBytes1 }, // POP
656 | { 0x5E, ENTRY_CopyBytes1 }, // POP
657 | { 0x5F, ENTRY_CopyBytes1 }, // POP
658 | { 0x60, ENTRY_CopyBytes1 }, // PUSHAD
659 | { 0x61, ENTRY_CopyBytes1 }, // POPAD
660 | { 0x62, ENTRY_CopyBytes2Mod }, // BOUND /r
661 | { 0x63, ENTRY_CopyBytes2Mod }, // ARPL /r
662 | { 0x64, ENTRY_CopyBytesPrefix }, // FS prefix
663 | { 0x65, ENTRY_CopyBytesPrefix }, // GS prefix
664 | { 0x66, ENTRY_Copy66 }, // Operand Prefix
665 | { 0x67, ENTRY_Copy67 }, // Address Prefix
666 | { 0x68, ENTRY_CopyBytes3Or5 }, // PUSH
667 | { 0x69, ENTRY_CopyBytes2ModOperand }, //
668 | { 0x6A, ENTRY_CopyBytes2 }, // PUSH
669 | { 0x6B, ENTRY_CopyBytes2Mod1 }, // IMUL /r ib
670 | { 0x6C, ENTRY_CopyBytes1 }, // INS
671 | { 0x6D, ENTRY_CopyBytes1 }, // INS
672 | { 0x6E, ENTRY_CopyBytes1 }, // OUTS/OUTSB
673 | { 0x6F, ENTRY_CopyBytes1 }, // OUTS/OUTSW
674 | { 0x70, ENTRY_CopyBytes2Jump }, // JO // 0f80
675 | { 0x71, ENTRY_CopyBytes2Jump }, // JNO // 0f81
676 | { 0x72, ENTRY_CopyBytes2Jump }, // JB/JC/JNAE // 0f82
677 | { 0x73, ENTRY_CopyBytes2Jump }, // JAE/JNB/JNC // 0f83
678 | { 0x74, ENTRY_CopyBytes2Jump }, // JE/JZ // 0f84
679 | { 0x75, ENTRY_CopyBytes2Jump }, // JNE/JNZ // 0f85
680 | { 0x76, ENTRY_CopyBytes2Jump }, // JBE/JNA // 0f86
681 | { 0x77, ENTRY_CopyBytes2Jump }, // JA/JNBE // 0f87
682 | { 0x78, ENTRY_CopyBytes2Jump }, // JS // 0f88
683 | { 0x79, ENTRY_CopyBytes2Jump }, // JNS // 0f89
684 | { 0x7A, ENTRY_CopyBytes2Jump }, // JP/JPE // 0f8a
685 | { 0x7B, ENTRY_CopyBytes2Jump }, // JNP/JPO // 0f8b
686 | { 0x7C, ENTRY_CopyBytes2Jump }, // JL/JNGE // 0f8c
687 | { 0x7D, ENTRY_CopyBytes2Jump }, // JGE/JNL // 0f8d
688 | { 0x7E, ENTRY_CopyBytes2Jump }, // JLE/JNG // 0f8e
689 | { 0x7F, ENTRY_CopyBytes2Jump }, // JG/JNLE // 0f8f
690 | { 0x80, ENTRY_CopyBytes2Mod1 }, // ADC/2 ib, etc.s
691 | { 0x81, ENTRY_CopyBytes2ModOperand }, //
692 | { 0x82, ENTRY_CopyBytes2 }, // MOV al,x
693 | { 0x83, ENTRY_CopyBytes2Mod1 }, // ADC/2 ib, etc.
694 | { 0x84, ENTRY_CopyBytes2Mod }, // TEST /r
695 | { 0x85, ENTRY_CopyBytes2Mod }, // TEST /r
696 | { 0x86, ENTRY_CopyBytes2Mod }, // XCHG /r @todo
697 | { 0x87, ENTRY_CopyBytes2Mod }, // XCHG /r @todo
698 | { 0x88, ENTRY_CopyBytes2Mod }, // MOV /r
699 | { 0x89, ENTRY_CopyBytes2Mod }, // MOV /r
700 | { 0x8A, ENTRY_CopyBytes2Mod }, // MOV /r
701 | { 0x8B, ENTRY_CopyBytes2Mod }, // MOV /r
702 | { 0x8C, ENTRY_CopyBytes2Mod }, // MOV /r
703 | { 0x8D, ENTRY_CopyBytes2Mod }, // LEA /r
704 | { 0x8E, ENTRY_CopyBytes2Mod }, // MOV /r
705 | { 0x8F, ENTRY_CopyBytes2Mod }, // POP /0
706 | { 0x90, ENTRY_CopyBytes1 }, // NOP
707 | { 0x91, ENTRY_CopyBytes1 }, // XCHG
708 | { 0x92, ENTRY_CopyBytes1 }, // XCHG
709 | { 0x93, ENTRY_CopyBytes1 }, // XCHG
710 | { 0x94, ENTRY_CopyBytes1 }, // XCHG
711 | { 0x95, ENTRY_CopyBytes1 }, // XCHG
712 | { 0x96, ENTRY_CopyBytes1 }, // XCHG
713 | { 0x97, ENTRY_CopyBytes1 }, // XCHG
714 | { 0x98, ENTRY_CopyBytes1 }, // CWDE
715 | { 0x99, ENTRY_CopyBytes1 }, // CDQ
716 | { 0x9A, ENTRY_CopyBytes5Or7Dynamic }, // CALL cp
717 | { 0x9B, ENTRY_CopyBytes1 }, // WAIT/FWAIT
718 | { 0x9C, ENTRY_CopyBytes1 }, // PUSHFD
719 | { 0x9D, ENTRY_CopyBytes1 }, // POPFD
720 | { 0x9E, ENTRY_CopyBytes1 }, // SAHF
721 | { 0x9F, ENTRY_CopyBytes1 }, // LAHF
722 | { 0xA0, ENTRY_CopyBytes3Or5Address }, // MOV
723 | { 0xA1, ENTRY_CopyBytes3Or5Address }, // MOV
724 | { 0xA2, ENTRY_CopyBytes3Or5Address }, // MOV
725 | { 0xA3, ENTRY_CopyBytes3Or5Address }, // MOV
726 | { 0xA4, ENTRY_CopyBytes1 }, // MOVS
727 | { 0xA5, ENTRY_CopyBytes1 }, // MOVS/MOVSD
728 | { 0xA6, ENTRY_CopyBytes1 }, // CMPS/CMPSB
729 | { 0xA7, ENTRY_CopyBytes1 }, // CMPS/CMPSW
730 | { 0xA8, ENTRY_CopyBytes2 }, // TEST
731 | { 0xA9, ENTRY_CopyBytes3Or5 }, // TEST
732 | { 0xAA, ENTRY_CopyBytes1 }, // STOS/STOSB
733 | { 0xAB, ENTRY_CopyBytes1 }, // STOS/STOSW
734 | { 0xAC, ENTRY_CopyBytes1 }, // LODS/LODSB
735 | { 0xAD, ENTRY_CopyBytes1 }, // LODS/LODSW
736 | { 0xAE, ENTRY_CopyBytes1 }, // SCAS/SCASB
737 | { 0xAF, ENTRY_CopyBytes1 }, // SCAS/SCASD
738 | { 0xB0, ENTRY_CopyBytes2 }, // MOV B0+rb
739 | { 0xB1, ENTRY_CopyBytes2 }, // MOV B0+rb
740 | { 0xB2, ENTRY_CopyBytes2 }, // MOV B0+rb
741 | { 0xB3, ENTRY_CopyBytes2 }, // MOV B0+rb
742 | { 0xB4, ENTRY_CopyBytes2 }, // MOV B0+rb
743 | { 0xB5, ENTRY_CopyBytes2 }, // MOV B0+rb
744 | { 0xB6, ENTRY_CopyBytes2 }, // MOV B0+rb
745 | { 0xB7, ENTRY_CopyBytes2 }, // MOV B0+rb
746 | { 0xB8, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb
747 | { 0xB9, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
748 | { 0xBA, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
749 | { 0xBB, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
750 | { 0xBC, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
751 | { 0xBD, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
752 | { 0xBE, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
753 | { 0xBF, ENTRY_CopyBytes3Or5 }, // MOV B8+rb
754 | { 0xC0, ENTRY_CopyBytes2Mod1 }, // RCL/2 ib, etc.
755 | { 0xC1, ENTRY_CopyBytes2Mod1 }, // RCL/2 ib, etc.
756 | { 0xC2, ENTRY_CopyBytes3 }, // RET
757 | { 0xC3, ENTRY_CopyBytes1 }, // RET
758 | { 0xC4, ENTRY_CopyBytes2Mod }, // LES
759 | { 0xC5, ENTRY_CopyBytes2Mod }, // LDS
760 | { 0xC6, ENTRY_CopyBytes2Mod1 }, // MOV
761 | { 0xC7, ENTRY_CopyBytes2ModOperand }, // MOV
762 | { 0xC8, ENTRY_CopyBytes4 }, // ENTER
763 | { 0xC9, ENTRY_CopyBytes1 }, // LEAVE
764 | { 0xCA, ENTRY_CopyBytes3Dynamic }, // RET
765 | { 0xCB, ENTRY_CopyBytes1Dynamic }, // RET
766 | { 0xCC, ENTRY_CopyBytes1Dynamic }, // INT 3
767 | { 0xCD, ENTRY_CopyBytes2Dynamic }, // INT ib
768 | { 0xCE, ENTRY_CopyBytes1Dynamic }, // INTO
769 | { 0xCF, ENTRY_CopyBytes1Dynamic }, // IRET
770 | { 0xD0, ENTRY_CopyBytes2Mod }, // RCL/2, etc.
771 | { 0xD1, ENTRY_CopyBytes2Mod }, // RCL/2, etc.
772 | { 0xD2, ENTRY_CopyBytes2Mod }, // RCL/2, etc.
773 | { 0xD3, ENTRY_CopyBytes2Mod }, // RCL/2, etc.
774 | { 0xD4, ENTRY_CopyBytes2 }, // AAM
775 | { 0xD5, ENTRY_CopyBytes2 }, // AAD
776 | { 0xD6, ENTRY_Invalid }, //
777 | { 0xD7, ENTRY_CopyBytes1 }, // XLAT/XLATB
778 | { 0xD8, ENTRY_CopyBytes2Mod }, // FADD, etc.
779 | { 0xD9, ENTRY_CopyBytes2Mod }, // F2XM1, etc.
780 | { 0xDA, ENTRY_CopyBytes2Mod }, // FLADD, etc.
781 | { 0xDB, ENTRY_CopyBytes2Mod }, // FCLEX, etc.
782 | { 0xDC, ENTRY_CopyBytes2Mod }, // FADD/0, etc.
783 | { 0xDD, ENTRY_CopyBytes2Mod }, // FFREE, etc.
784 | { 0xDE, ENTRY_CopyBytes2Mod }, // FADDP, etc.
785 | { 0xDF, ENTRY_CopyBytes2Mod }, // FBLD/4, etc.
786 | { 0xE0, ENTRY_CopyBytes2CantJump }, // LOOPNE cb
787 | { 0xE1, ENTRY_CopyBytes2CantJump }, // LOOPE cb
788 | { 0xE2, ENTRY_CopyBytes2CantJump }, // LOOP cb
789 | { 0xE3, ENTRY_CopyBytes2Jump }, // JCXZ/JECXZ
790 | { 0xE4, ENTRY_CopyBytes2 }, // IN ib
791 | { 0xE5, ENTRY_CopyBytes2 }, // IN id
792 | { 0xE6, ENTRY_CopyBytes2 }, // OUT ib
793 | { 0xE7, ENTRY_CopyBytes2 }, // OUT ib
794 | { 0xE8, ENTRY_CopyBytes3Or5Target }, // CALL cd
795 | { 0xE9, ENTRY_CopyBytes3Or5Target }, // JMP cd
796 | { 0xEA, ENTRY_CopyBytes5Or7Dynamic }, // JMP cp
797 | { 0xEB, ENTRY_CopyBytes2Jump }, // JMP cb
798 | { 0xEC, ENTRY_CopyBytes1 }, // IN ib
799 | { 0xED, ENTRY_CopyBytes1 }, // IN id
800 | { 0xEE, ENTRY_CopyBytes1 }, // OUT
801 | { 0xEF, ENTRY_CopyBytes1 }, // OUT
802 | { 0xF0, ENTRY_CopyBytesPrefix }, // LOCK prefix
803 | { 0xF1, ENTRY_Invalid }, //
804 | { 0xF2, ENTRY_CopyBytesPrefix }, // REPNE prefix
805 | { 0xF3, ENTRY_CopyBytesPrefix }, // REPE prefix
806 | { 0xF4, ENTRY_CopyBytes1 }, // HLT
807 | { 0xF5, ENTRY_CopyBytes1 }, // CMC
808 | { 0xF6, ENTRY_CopyF6 }, // TEST/0, DIV/6
809 | { 0xF7, ENTRY_CopyF7 }, // TEST/0, DIV/6
810 | { 0xF8, ENTRY_CopyBytes1 }, // CLC
811 | { 0xF9, ENTRY_CopyBytes1 }, // STC
812 | { 0xFA, ENTRY_CopyBytes1 }, // CLI
813 | { 0xFB, ENTRY_CopyBytes1 }, // STI
814 | { 0xFC, ENTRY_CopyBytes1 }, // CLD
815 | { 0xFD, ENTRY_CopyBytes1 }, // STD
816 | { 0xFE, ENTRY_CopyBytes2Mod }, // DEC/1,INC/0
817 | { 0xFF, ENTRY_CopyFF }, // CALL/2
818 | { 0, ENTRY_End },
819 | };
820 |
821 | const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable0F[257] =
822 | {
823 | { 0x00, ENTRY_CopyBytes2Mod }, // LLDT/2, etc.
824 | { 0x01, ENTRY_CopyBytes2Mod }, // INVLPG/7, etc.
825 | { 0x02, ENTRY_CopyBytes2Mod }, // LAR/r
826 | { 0x03, ENTRY_CopyBytes2Mod }, // LSL/r
827 | { 0x04, ENTRY_Invalid }, // _04
828 | { 0x05, ENTRY_Invalid }, // _05
829 | { 0x06, ENTRY_CopyBytes2 }, // CLTS
830 | { 0x07, ENTRY_Invalid }, // _07
831 | { 0x08, ENTRY_CopyBytes2 }, // INVD
832 | { 0x09, ENTRY_CopyBytes2 }, // WBINVD
833 | { 0x0A, ENTRY_Invalid }, // _0A
834 | { 0x0B, ENTRY_CopyBytes2 }, // UD2
835 | { 0x0C, ENTRY_Invalid }, // _0C
836 | { 0x0D, ENTRY_CopyBytes2Mod }, // PREFETCH
837 | { 0x0E, ENTRY_CopyBytes2 }, // FEMMS
838 | { 0x0F, ENTRY_CopyBytes3Mod }, // 3DNow Opcodes
839 | { 0x10, ENTRY_CopyBytes2Mod }, // MOVSS MOVUPD MOVSD
840 | { 0x11, ENTRY_CopyBytes2Mod }, // MOVSS MOVUPD MOVSD
841 | { 0x12, ENTRY_CopyBytes2Mod }, // MOVLPD
842 | { 0x13, ENTRY_CopyBytes2Mod }, // MOVLPD
843 | { 0x14, ENTRY_CopyBytes2Mod }, // UNPCKLPD
844 | { 0x15, ENTRY_CopyBytes2Mod }, // UNPCKHPD
845 | { 0x16, ENTRY_CopyBytes2Mod }, // MOVHPD
846 | { 0x17, ENTRY_CopyBytes2Mod }, // MOVHPD
847 | { 0x18, ENTRY_CopyBytes2Mod }, // PREFETCHINTA...
848 | { 0x19, ENTRY_Invalid }, // _19
849 | { 0x1A, ENTRY_Invalid }, // _1A
850 | { 0x1B, ENTRY_Invalid }, // _1B
851 | { 0x1C, ENTRY_Invalid }, // _1C
852 | { 0x1D, ENTRY_Invalid }, // _1D
853 | { 0x1E, ENTRY_Invalid }, // _1E
854 | { 0x1F, ENTRY_CopyBytes2Mod }, // NOP/r
855 | { 0x20, ENTRY_CopyBytes2Mod }, // MOV/r
856 | { 0x21, ENTRY_CopyBytes2Mod }, // MOV/r
857 | { 0x22, ENTRY_CopyBytes2Mod }, // MOV/r
858 | { 0x23, ENTRY_CopyBytes2Mod }, // MOV/r
859 | { 0x24, ENTRY_Invalid }, // _24
860 | { 0x25, ENTRY_Invalid }, // _25
861 | { 0x26, ENTRY_Invalid }, // _26
862 | { 0x27, ENTRY_Invalid }, // _27
863 | { 0x28, ENTRY_CopyBytes2Mod }, // MOVAPS MOVAPD
864 | { 0x29, ENTRY_CopyBytes2Mod }, // MOVAPS MOVAPD
865 | { 0x2A, ENTRY_CopyBytes2Mod }, // CVPI2PS &
866 | { 0x2B, ENTRY_CopyBytes2Mod }, // MOVNTPS MOVNTPD
867 | { 0x2C, ENTRY_CopyBytes2Mod }, // CVTTPS2PI &
868 | { 0x2D, ENTRY_CopyBytes2Mod }, // CVTPS2PI &
869 | { 0x2E, ENTRY_CopyBytes2Mod }, // UCOMISS UCOMISD
870 | { 0x2F, ENTRY_CopyBytes2Mod }, // COMISS COMISD
871 | { 0x30, ENTRY_CopyBytes2 }, // WRMSR
872 | { 0x31, ENTRY_CopyBytes2 }, // RDTSC
873 | { 0x32, ENTRY_CopyBytes2 }, // RDMSR
874 | { 0x33, ENTRY_CopyBytes2 }, // RDPMC
875 | { 0x34, ENTRY_CopyBytes2 }, // SYSENTER
876 | { 0x35, ENTRY_CopyBytes2 }, // SYSEXIT
877 | { 0x36, ENTRY_Invalid }, // _36
878 | { 0x37, ENTRY_Invalid }, // _37
879 | { 0x38, ENTRY_Invalid }, // _38
880 | { 0x39, ENTRY_Invalid }, // _39
881 | { 0x3A, ENTRY_Invalid }, // _3A
882 | { 0x3B, ENTRY_Invalid }, // _3B
883 | { 0x3C, ENTRY_Invalid }, // _3C
884 | { 0x3D, ENTRY_Invalid }, // _3D
885 | { 0x3E, ENTRY_Invalid }, // _3E
886 | { 0x3F, ENTRY_Invalid }, // _3F
887 | { 0x40, ENTRY_CopyBytes2Mod }, // CMOVO (0F 40)
888 | { 0x41, ENTRY_CopyBytes2Mod }, // CMOVNO (0F 41)
889 | { 0x42, ENTRY_CopyBytes2Mod }, // CMOVB & CMOVNE (0F 42)
890 | { 0x43, ENTRY_CopyBytes2Mod }, // CMOVAE & CMOVNB (0F 43)
891 | { 0x44, ENTRY_CopyBytes2Mod }, // CMOVE & CMOVZ (0F 44)
892 | { 0x45, ENTRY_CopyBytes2Mod }, // CMOVNE & CMOVNZ (0F 45)
893 | { 0x46, ENTRY_CopyBytes2Mod }, // CMOVBE & CMOVNA (0F 46)
894 | { 0x47, ENTRY_CopyBytes2Mod }, // CMOVA & CMOVNBE (0F 47)
895 | { 0x48, ENTRY_CopyBytes2Mod }, // CMOVS (0F 48)
896 | { 0x49, ENTRY_CopyBytes2Mod }, // CMOVNS (0F 49)
897 | { 0x4A, ENTRY_CopyBytes2Mod }, // CMOVP & CMOVPE (0F 4A)
898 | { 0x4B, ENTRY_CopyBytes2Mod }, // CMOVNP & CMOVPO (0F 4B)
899 | { 0x4C, ENTRY_CopyBytes2Mod }, // CMOVL & CMOVNGE (0F 4C)
900 | { 0x4D, ENTRY_CopyBytes2Mod }, // CMOVGE & CMOVNL (0F 4D)
901 | { 0x4E, ENTRY_CopyBytes2Mod }, // CMOVLE & CMOVNG (0F 4E)
902 | { 0x4F, ENTRY_CopyBytes2Mod }, // CMOVG & CMOVNLE (0F 4F)
903 | { 0x50, ENTRY_CopyBytes2Mod }, // MOVMSKPD MOVMSKPD
904 | { 0x51, ENTRY_CopyBytes2Mod }, // SQRTPS &
905 | { 0x52, ENTRY_CopyBytes2Mod }, // RSQRTTS RSQRTPS
906 | { 0x53, ENTRY_CopyBytes2Mod }, // RCPPS RCPSS
907 | { 0x54, ENTRY_CopyBytes2Mod }, // ANDPS ANDPD
908 | { 0x55, ENTRY_CopyBytes2Mod }, // ANDNPS ANDNPD
909 | { 0x56, ENTRY_CopyBytes2Mod }, // ORPS ORPD
910 | { 0x57, ENTRY_CopyBytes2Mod }, // XORPS XORPD
911 | { 0x58, ENTRY_CopyBytes2Mod }, // ADDPS &
912 | { 0x59, ENTRY_CopyBytes2Mod }, // MULPS &
913 | { 0x5A, ENTRY_CopyBytes2Mod }, // CVTPS2PD &
914 | { 0x5B, ENTRY_CopyBytes2Mod }, // CVTDQ2PS &
915 | { 0x5C, ENTRY_CopyBytes2Mod }, // SUBPS &
916 | { 0x5D, ENTRY_CopyBytes2Mod }, // MINPS &
917 | { 0x5E, ENTRY_CopyBytes2Mod }, // DIVPS &
918 | { 0x5F, ENTRY_CopyBytes2Mod }, // MASPS &
919 | { 0x60, ENTRY_CopyBytes2Mod }, // PUNPCKLBW/r
920 | { 0x61, ENTRY_CopyBytes2Mod }, // PUNPCKLWD/r
921 | { 0x62, ENTRY_CopyBytes2Mod }, // PUNPCKLWD/r
922 | { 0x63, ENTRY_CopyBytes2Mod }, // PACKSSWB/r
923 | { 0x64, ENTRY_CopyBytes2Mod }, // PCMPGTB/r
924 | { 0x65, ENTRY_CopyBytes2Mod }, // PCMPGTW/r
925 | { 0x66, ENTRY_CopyBytes2Mod }, // PCMPGTD/r
926 | { 0x67, ENTRY_CopyBytes2Mod }, // PACKUSWB/r
927 | { 0x68, ENTRY_CopyBytes2Mod }, // PUNPCKHBW/r
928 | { 0x69, ENTRY_CopyBytes2Mod }, // PUNPCKHWD/r
929 | { 0x6A, ENTRY_CopyBytes2Mod }, // PUNPCKHDQ/r
930 | { 0x6B, ENTRY_CopyBytes2Mod }, // PACKSSDW/r
931 | { 0x6C, ENTRY_CopyBytes2Mod }, // PUNPCKLQDQ
932 | { 0x6D, ENTRY_CopyBytes2Mod }, // PUNPCKHQDQ
933 | { 0x6E, ENTRY_CopyBytes2Mod }, // MOVD/r
934 | { 0x6F, ENTRY_CopyBytes2Mod }, // MOV/r
935 | { 0x70, ENTRY_CopyBytes2Mod1 }, // PSHUFW/r ib
936 | { 0x71, ENTRY_CopyBytes2Mod1 }, // PSLLW/6 ib,PSRAW/4 ib,PSRLW/2 ib
937 | { 0x72, ENTRY_CopyBytes2Mod1 }, // PSLLD/6 ib,PSRAD/4 ib,PSRLD/2 ib
938 | { 0x73, ENTRY_CopyBytes2Mod1 }, // PSLLQ/6 ib,PSRLQ/2 ib
939 | { 0x74, ENTRY_CopyBytes2Mod }, // PCMPEQB/r
940 | { 0x75, ENTRY_CopyBytes2Mod }, // PCMPEQW/r
941 | { 0x76, ENTRY_CopyBytes2Mod }, // PCMPEQD/r
942 | { 0x77, ENTRY_CopyBytes2 }, // EMMS
943 | { 0x78, ENTRY_Invalid }, // _78
944 | { 0x79, ENTRY_Invalid }, // _79
945 | { 0x7A, ENTRY_Invalid }, // _7A
946 | { 0x7B, ENTRY_Invalid }, // _7B
947 | { 0x7C, ENTRY_Invalid }, // _7C
948 | { 0x7D, ENTRY_Invalid }, // _7D
949 | { 0x7E, ENTRY_CopyBytes2Mod }, // MOVD/r
950 | { 0x7F, ENTRY_CopyBytes2Mod }, // MOV/r
951 | { 0x80, ENTRY_CopyBytes3Or5Target }, // JO
952 | { 0x81, ENTRY_CopyBytes3Or5Target }, // JNO
953 | { 0x82, ENTRY_CopyBytes3Or5Target }, // JB,JC,JNAE
954 | { 0x83, ENTRY_CopyBytes3Or5Target }, // JAE,JNB,JNC
955 | { 0x84, ENTRY_CopyBytes3Or5Target }, // JE,JZ,JZ
956 | { 0x85, ENTRY_CopyBytes3Or5Target }, // JNE,JNZ
957 | { 0x86, ENTRY_CopyBytes3Or5Target }, // JBE,JNA
958 | { 0x87, ENTRY_CopyBytes3Or5Target }, // JA,JNBE
959 | { 0x88, ENTRY_CopyBytes3Or5Target }, // JS
960 | { 0x89, ENTRY_CopyBytes3Or5Target }, // JNS
961 | { 0x8A, ENTRY_CopyBytes3Or5Target }, // JP,JPE
962 | { 0x8B, ENTRY_CopyBytes3Or5Target }, // JNP,JPO
963 | { 0x8C, ENTRY_CopyBytes3Or5Target }, // JL,NGE
964 | { 0x8D, ENTRY_CopyBytes3Or5Target }, // JGE,JNL
965 | { 0x8E, ENTRY_CopyBytes3Or5Target }, // JLE,JNG
966 | { 0x8F, ENTRY_CopyBytes3Or5Target }, // JG,JNLE
967 | { 0x90, ENTRY_CopyBytes2Mod }, // CMOVO (0F 40)
968 | { 0x91, ENTRY_CopyBytes2Mod }, // CMOVNO (0F 41)
969 | { 0x92, ENTRY_CopyBytes2Mod }, // CMOVB & CMOVC & CMOVNAE (0F 42)
970 | { 0x93, ENTRY_CopyBytes2Mod }, // CMOVAE & CMOVNB & CMOVNC (0F 43)
971 | { 0x94, ENTRY_CopyBytes2Mod }, // CMOVE & CMOVZ (0F 44)
972 | { 0x95, ENTRY_CopyBytes2Mod }, // CMOVNE & CMOVNZ (0F 45)
973 | { 0x96, ENTRY_CopyBytes2Mod }, // CMOVBE & CMOVNA (0F 46)
974 | { 0x97, ENTRY_CopyBytes2Mod }, // CMOVA & CMOVNBE (0F 47)
975 | { 0x98, ENTRY_CopyBytes2Mod }, // CMOVS (0F 48)
976 | { 0x99, ENTRY_CopyBytes2Mod }, // CMOVNS (0F 49)
977 | { 0x9A, ENTRY_CopyBytes2Mod }, // CMOVP & CMOVPE (0F 4A)
978 | { 0x9B, ENTRY_CopyBytes2Mod }, // CMOVNP & CMOVPO (0F 4B)
979 | { 0x9C, ENTRY_CopyBytes2Mod }, // CMOVL & CMOVNGE (0F 4C)
980 | { 0x9D, ENTRY_CopyBytes2Mod }, // CMOVGE & CMOVNL (0F 4D)
981 | { 0x9E, ENTRY_CopyBytes2Mod }, // CMOVLE & CMOVNG (0F 4E)
982 | { 0x9F, ENTRY_CopyBytes2Mod }, // CMOVG & CMOVNLE (0F 4F)
983 | { 0xA0, ENTRY_CopyBytes2 }, // PUSH
984 | { 0xA1, ENTRY_CopyBytes2 }, // POP
985 | { 0xA2, ENTRY_CopyBytes2 }, // CPUID
986 | { 0xA3, ENTRY_CopyBytes2Mod }, // BT (0F A3)
987 | { 0xA4, ENTRY_CopyBytes2Mod1 }, // SHLD
988 | { 0xA5, ENTRY_CopyBytes2Mod }, // SHLD
989 | { 0xA6, ENTRY_Invalid }, // _A6
990 | { 0xA7, ENTRY_Invalid }, // _A7
991 | { 0xA8, ENTRY_CopyBytes2 }, // PUSH
992 | { 0xA9, ENTRY_CopyBytes2 }, // POP
993 | { 0xAA, ENTRY_CopyBytes2 }, // RSM
994 | { 0xAB, ENTRY_CopyBytes2Mod }, // BTS (0F AB)
995 | { 0xAC, ENTRY_CopyBytes2Mod1 }, // SHRD
996 | { 0xAD, ENTRY_CopyBytes2Mod }, // SHRD
997 | { 0xAE, ENTRY_CopyBytes2Mod }, // FXRSTOR/1,FXSAVE/0
998 | { 0xAF, ENTRY_CopyBytes2Mod }, // IMUL (0F AF)
999 | { 0xB0, ENTRY_CopyBytes2Mod }, // CMPXCHG (0F B0)
1000 | { 0xB1, ENTRY_CopyBytes2Mod }, // CMPXCHG (0F B1)
1001 | { 0xB2, ENTRY_CopyBytes2Mod }, // LSS/r
1002 | { 0xB3, ENTRY_CopyBytes2Mod }, // BTR (0F B3)
1003 | { 0xB4, ENTRY_CopyBytes2Mod }, // LFS/r
1004 | { 0xB5, ENTRY_CopyBytes2Mod }, // LGS/r
1005 | { 0xB6, ENTRY_CopyBytes2Mod }, // MOVZX/r
1006 | { 0xB7, ENTRY_CopyBytes2Mod }, // MOVZX/r
1007 | { 0xB8, ENTRY_Invalid }, // _B8
1008 | { 0xB9, ENTRY_Invalid }, // _B9
1009 | { 0xBA, ENTRY_CopyBytes2Mod1 }, // BT & BTC & BTR & BTS (0F BA)
1010 | { 0xBB, ENTRY_CopyBytes2Mod }, // BTC (0F BB)
1011 | { 0xBC, ENTRY_CopyBytes2Mod }, // BSF (0F BC)
1012 | { 0xBD, ENTRY_CopyBytes2Mod }, // BSR (0F BD)
1013 | { 0xBE, ENTRY_CopyBytes2Mod }, // MOVSX/r
1014 | { 0xBF, ENTRY_CopyBytes2Mod }, // MOVSX/r
1015 | { 0xC0, ENTRY_CopyBytes2Mod }, // XADD/r
1016 | { 0xC1, ENTRY_CopyBytes2Mod }, // XADD/r
1017 | { 0xC2, ENTRY_CopyBytes2Mod }, // CMPPS &
1018 | { 0xC3, ENTRY_CopyBytes2Mod }, // MOVNTI
1019 | { 0xC4, ENTRY_CopyBytes2Mod1 }, // PINSRW /r ib
1020 | { 0xC5, ENTRY_CopyBytes2Mod1 }, // PEXTRW /r ib
1021 | { 0xC6, ENTRY_CopyBytes2Mod1 }, // SHUFPS & SHUFPD
1022 | { 0xC7, ENTRY_CopyBytes2Mod }, // CMPXCHG8B (0F C7)
1023 | { 0xC8, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
1024 | { 0xC9, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
1025 | { 0xCA, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
1026 | { 0xCB, ENTRY_CopyBytes2 }, //CVTPD2PI BSWAP 0F C8 + rd
1027 | { 0xCC, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
1028 | { 0xCD, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
1029 | { 0xCE, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
1030 | { 0xCF, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd
1031 | { 0xD0, ENTRY_Invalid }, // _D0
1032 | { 0xD1, ENTRY_CopyBytes2Mod }, // PSRLW/r
1033 | { 0xD2, ENTRY_CopyBytes2Mod }, // PSRLD/r
1034 | { 0xD3, ENTRY_CopyBytes2Mod }, // PSRLQ/r
1035 | { 0xD4, ENTRY_CopyBytes2Mod }, // PADDQ
1036 | { 0xD5, ENTRY_CopyBytes2Mod }, // PMULLW/r
1037 | { 0xD6, ENTRY_CopyBytes2Mod }, // MOVDQ2Q / MOVQ2DQ
1038 | { 0xD7, ENTRY_CopyBytes2Mod }, // PMOVMSKB/r
1039 | { 0xD8, ENTRY_CopyBytes2Mod }, // PSUBUSB/r
1040 | { 0xD9, ENTRY_CopyBytes2Mod }, // PSUBUSW/r
1041 | { 0xDA, ENTRY_CopyBytes2Mod }, // PMINUB/r
1042 | { 0xDB, ENTRY_CopyBytes2Mod }, // PAND/r
1043 | { 0xDC, ENTRY_CopyBytes2Mod }, // PADDUSB/r
1044 | { 0xDD, ENTRY_CopyBytes2Mod }, // PADDUSW/r
1045 | { 0xDE, ENTRY_CopyBytes2Mod }, // PMAXUB/r
1046 | { 0xDF, ENTRY_CopyBytes2Mod }, // PANDN/r
1047 | { 0xE0, ENTRY_CopyBytes2Mod }, // PAVGB
1048 | { 0xE1, ENTRY_CopyBytes2Mod }, // PSRAW/r
1049 | { 0xE2, ENTRY_CopyBytes2Mod }, // PSRAD/r
1050 | { 0xE3, ENTRY_CopyBytes2Mod }, // PAVGW
1051 | { 0xE4, ENTRY_CopyBytes2Mod }, // PMULHUW/r
1052 | { 0xE5, ENTRY_CopyBytes2Mod }, // PMULHW/r
1053 | { 0xE6, ENTRY_CopyBytes2Mod }, // CTDQ2PD &
1054 | { 0xE7, ENTRY_CopyBytes2Mod }, // MOVNTQ
1055 | { 0xE8, ENTRY_CopyBytes2Mod }, // PSUBB/r
1056 | { 0xE9, ENTRY_CopyBytes2Mod }, // PSUBW/r
1057 | { 0xEA, ENTRY_CopyBytes2Mod }, // PMINSW/r
1058 | { 0xEB, ENTRY_CopyBytes2Mod }, // POR/r
1059 | { 0xEC, ENTRY_CopyBytes2Mod }, // PADDSB/r
1060 | { 0xED, ENTRY_CopyBytes2Mod }, // PADDSW/r
1061 | { 0xEE, ENTRY_CopyBytes2Mod }, // PMAXSW /r
1062 | { 0xEF, ENTRY_CopyBytes2Mod }, // PXOR/r
1063 | { 0xF0, ENTRY_Invalid }, // _F0
1064 | { 0xF1, ENTRY_CopyBytes2Mod }, // PSLLW/r
1065 | { 0xF2, ENTRY_CopyBytes2Mod }, // PSLLD/r
1066 | { 0xF3, ENTRY_CopyBytes2Mod }, // PSLLQ/r
1067 | { 0xF4, ENTRY_CopyBytes2Mod }, // PMULUDQ/r
1068 | { 0xF5, ENTRY_CopyBytes2Mod }, // PMADDWD/r
1069 | { 0xF6, ENTRY_CopyBytes2Mod }, // PSADBW/r
1070 | { 0xF7, ENTRY_CopyBytes2Mod }, // MASKMOVQ
1071 | { 0xF8, ENTRY_CopyBytes2Mod }, // PSUBB/r
1072 | { 0xF9, ENTRY_CopyBytes2Mod }, // PSUBW/r
1073 | { 0xFA, ENTRY_CopyBytes2Mod }, // PSUBD/r
1074 | { 0xFB, ENTRY_CopyBytes2Mod }, // FSUBQ/r
1075 | { 0xFC, ENTRY_CopyBytes2Mod }, // PADDB/r
1076 | { 0xFD, ENTRY_CopyBytes2Mod }, // PADDW/r
1077 | { 0xFE, ENTRY_CopyBytes2Mod }, // PADDD/r
1078 | { 0xFF, ENTRY_Invalid }, // _FF
1079 | { 0, ENTRY_End },
1080 | };
1081 |
1082 | BOOL CDetourDis::SanityCheckSystem()
1083 | {
1084 | ULONG n = 0;
1085 | for (; n < 256; n++) {
1086 | REFCOPYENTRY pEntry = &s_rceCopyTable[n];
1087 |
1088 | if (n != pEntry->nOpcode) {
1089 | ASSERT(n == pEntry->nOpcode);
1090 | return FALSE;
1091 | }
1092 | }
1093 | if (s_rceCopyTable[256].pfCopy != NULL) {
1094 | ASSERT(!"Missing end marker.");
1095 | return FALSE;
1096 | }
1097 |
1098 | for (n = 0; n < 256; n++) {
1099 | REFCOPYENTRY pEntry = &s_rceCopyTable0F[n];
1100 |
1101 | if (n != pEntry->nOpcode) {
1102 | ASSERT(n == pEntry->nOpcode);
1103 | return FALSE;
1104 | }
1105 | }
1106 | if (s_rceCopyTable0F[256].pfCopy != NULL) {
1107 | ASSERT(!"Missing end marker.");
1108 | return FALSE;
1109 | }
1110 |
1111 | return TRUE;
1112 | }
1113 | #endif // defined(DETOURS_X64) || defined(DETOURS_X86)
1114 |
1115 | /////////////////////////////////////////////////////////// IA64 Disassembler.
1116 | //
1117 | #ifdef DETOURS_IA64
1118 | #error Feature not supported in this release.
1119 |
1120 |
1121 |
1122 |
1123 |
1124 |
1125 |
1126 |
1127 |
1128 |
1129 |
1130 |
1131 |
1132 |
1133 |
1134 |
1135 |
1136 |
1137 |
1138 |
1139 |
1140 |
1141 |
1142 |
1143 |
1144 |
1145 |
1146 |
1147 |
1148 |
1149 |
1150 |
1151 |
1152 |
1153 |
1154 |
1155 |
1156 |
1157 |
1158 |
1159 |
1160 |
1161 |
1162 |
1163 |
1164 |
1165 |
1166 |
1167 |
1168 |
1169 |
1170 |
1171 |
1172 |
1173 |
1174 |
1175 |
1176 |
1177 |
1178 |
1179 |
1180 |
1181 |
1182 |
1183 |
1184 |
1185 |
1186 |
1187 |
1188 |
1189 |
1190 |
1191 |
1192 |
1193 |
1194 |
1195 |
1196 |
1197 |
1198 |
1199 |
1200 |
1201 |
1202 |
1203 |
1204 |
1205 |
1206 |
1207 |
1208 |
1209 |
1210 |
1211 |
1212 |
1213 |
1214 |
1215 |
1216 |
1217 |
1218 |
1219 |
1220 |
1221 |
1222 |
1223 |
1224 |
1225 |
1226 |
1227 |
1228 |
1229 |
1230 |
1231 |
1232 |
1233 |
1234 |
1235 |
1236 |
1237 |
1238 |
1239 |
1240 |
1241 |
1242 |
1243 |
1244 |
1245 |
1246 |
1247 |
1248 |
1249 |
1250 |
1251 |
1252 |
1253 |
1254 |
1255 |
1256 |
1257 |
1258 |
1259 |
1260 |
1261 |
1262 |
1263 |
1264 |
1265 |
1266 |
1267 |
1268 |
1269 |
1270 |
1271 |
1272 |
1273 |
1274 |
1275 |
1276 |
1277 |
1278 |
1279 |
1280 |
1281 |
1282 |
1283 |
1284 |
1285 |
1286 |
1287 |
1288 |
1289 |
1290 |
1291 |
1292 |
1293 |
1294 |
1295 |
1296 |
1297 |
1298 |
1299 |
1300 |
1301 |
1302 |
1303 |
1304 |
1305 |
1306 |
1307 |
1308 |
1309 |
1310 |
1311 |
1312 |
1313 |
1314 |
1315 |
1316 |
1317 |
1318 |
1319 |
1320 |
1321 |
1322 |
1323 |
1324 |
1325 |
1326 |
1327 |
1328 |
1329 |
1330 |
1331 |
1332 |
1333 |
1334 |
1335 |
1336 |
1337 |
1338 |
1339 |
1340 |
1341 |
1342 |
1343 |
1344 |
1345 |
1346 |
1347 |
1348 |
1349 |
1350 |
1351 |
1352 |
1353 |
1354 |
1355 |
1356 |
1357 |
1358 |
1359 |
1360 |
1361 |
1362 |
1363 |
1364 |
1365 |
1366 |
1367 |
1368 |
1369 |
1370 |
1371 |
1372 |
1373 |
1374 |
1375 |
1376 |
1377 |
1378 |
1379 |
1380 |
1381 |
1382 |
1383 |
1384 |
1385 |
1386 |
1387 |
1388 |
1389 |
1390 |
1391 |
1392 |
1393 |
1394 |
1395 |
1396 |
1397 |
1398 |
1399 |
1400 |
1401 |
1402 |
1403 |
1404 |
1405 |
1406 |
1407 |
1408 |
1409 |
1410 |
1411 |
1412 |
1413 |
1414 |
1415 |
1416 |
1417 |
1418 |
1419 |
1420 |
1421 |
1422 |
1423 |
1424 |
1425 |
1426 |
1427 |
1428 |
1429 |
1430 |
1431 |
1432 |
1433 |
1434 |
1435 |
1436 |
1437 |
1438 |
1439 |
1440 |
1441 |
1442 |
1443 |
1444 |
1445 |
1446 |
1447 |
1448 |
1449 |
1450 |
1451 |
1452 |
1453 |
1454 |
1455 |
1456 |
1457 |
1458 |
1459 |
1460 |
1461 |
1462 |
1463 |
1464 |
1465 |
1466 |
1467 |
1468 |
1469 |
1470 |
1471 |
1472 |
1473 |
1474 |
1475 |
1476 |
1477 |
1478 |
1479 |
1480 |
1481 |
1482 |
1483 |
1484 |
1485 |
1486 |
1487 |
1488 |
1489 |
1490 |
1491 |
1492 |
1493 |
1494 |
1495 |
1496 |
1497 |
1498 |
1499 |
1500 |
1501 |
1502 |
1503 |
1504 |
1505 |
1506 |
1507 |
1508 |
1509 |
1510 |
1511 |
1512 |
1513 |
1514 |
1515 |
1516 |
1517 |
1518 |
1519 |
1520 |
1521 |
1522 |
1523 |
1524 |
1525 |
1526 |
1527 |
1528 |
1529 |
1530 |
1531 |
1532 |
1533 |
1534 |
1535 |
1536 |
1537 |
1538 |
1539 |
1540 |
1541 |
1542 |
1543 |
1544 |
1545 |
1546 |
1547 |
1548 |
1549 |
1550 |
1551 |
1552 |
1553 |
1554 |
1555 |
1556 |
1557 |
1558 |
1559 |
1560 |
1561 |
1562 |
1563 |
1564 |
1565 |
1566 |
1567 |
1568 |
1569 |
1570 |
1571 |
1572 |
1573 |
1574 |
1575 |
1576 |
1577 |
1578 |
1579 |
1580 |
1581 |
1582 |
1583 |
1584 |
1585 |
1586 |
1587 |
1588 |
1589 |
1590 |
1591 |
1592 | #endif // DETOURS_IA64
1593 |
1594 | #ifdef DETOURS_ARM
1595 | #error Feature not supported in this release.
1596 |
1597 |
1598 |
1599 |
1600 |
1601 |
1602 |
1603 |
1604 |
1605 |
1606 |
1607 |
1608 |
1609 |
1610 |
1611 |
1612 |
1613 |
1614 |
1615 |
1616 |
1617 |
1618 |
1619 |
1620 |
1621 |
1622 |
1623 |
1624 |
1625 |
1626 |
1627 |
1628 |
1629 |
1630 |
1631 |
1632 |
1633 |
1634 |
1635 |
1636 |
1637 |
1638 |
1639 |
1640 |
1641 |
1642 |
1643 |
1644 |
1645 |
1646 |
1647 |
1648 |
1649 |
1650 |
1651 |
1652 |
1653 |
1654 |
1655 |
1656 |
1657 |
1658 |
1659 |
1660 |
1661 |
1662 |
1663 |
1664 |
1665 |
1666 |
1667 |
1668 |
1669 |
1670 |
1671 |
1672 |
1673 |
1674 |
1675 |
1676 |
1677 |
1678 |
1679 |
1680 |
1681 |
1682 |
1683 |
1684 |
1685 |
1686 |
1687 |
1688 |
1689 |
1690 |
1691 |
1692 |
1693 |
1694 |
1695 |
1696 |
1697 |
1698 |
1699 |
1700 |
1701 |
1702 |
1703 |
1704 |
1705 |
1706 |
1707 |
1708 |
1709 |
1710 |
1711 |
1712 |
1713 |
1714 |
1715 |
1716 |
1717 |
1718 |
1719 |
1720 |
1721 |
1722 |
1723 |
1724 |
1725 |
1726 |
1727 |
1728 |
1729 |
1730 |
1731 |
1732 |
1733 |
1734 |
1735 |
1736 |
1737 |
1738 |
1739 |
1740 |
1741 |
1742 |
1743 |
1744 |
1745 |
1746 |
1747 |
1748 |
1749 |
1750 |
1751 |
1752 |
1753 |
1754 |
1755 |
1756 |
1757 |
1758 |
1759 |
1760 |
1761 |
1762 |
1763 |
1764 |
1765 |
1766 |
1767 |
1768 |
1769 |
1770 |
1771 |
1772 |
1773 |
1774 |
1775 |
1776 |
1777 |
1778 |
1779 |
1780 |
1781 |
1782 |
1783 |
1784 |
1785 |
1786 |
1787 |
1788 |
1789 |
1790 |
1791 |
1792 |
1793 |
1794 |
1795 |
1796 |
1797 |
1798 |
1799 |
1800 |
1801 |
1802 |
1803 |
1804 |
1805 |
1806 |
1807 |
1808 |
1809 |
1810 |
1811 |
1812 |
1813 |
1814 |
1815 |
1816 |
1817 |
1818 |
1819 |
1820 |
1821 |
1822 |
1823 |
1824 |
1825 |
1826 |
1827 |
1828 |
1829 |
1830 |
1831 |
1832 |
1833 |
1834 |
1835 |
1836 |
1837 |
1838 |
1839 |
1840 |
1841 |
1842 |
1843 |
1844 |
1845 |
1846 |
1847 |
1848 |
1849 |
1850 |
1851 |
1852 |
1853 |
1854 |
1855 |
1856 |
1857 |
1858 |
1859 |
1860 |
1861 |
1862 |
1863 |
1864 |
1865 |
1866 |
1867 |
1868 |
1869 |
1870 |
1871 |
1872 |
1873 |
1874 |
1875 |
1876 |
1877 |
1878 |
1879 |
1880 |
1881 |
1882 |
1883 |
1884 |
1885 |
1886 |
1887 |
1888 |
1889 |
1890 |
1891 |
1892 |
1893 |
1894 |
1895 |
1896 |
1897 |
1898 |
1899 |
1900 |
1901 |
1902 |
1903 |
1904 |
1905 |
1906 |
1907 |
1908 |
1909 |
1910 |
1911 |
1912 |
1913 |
1914 |
1915 |
1916 |
1917 |
1918 |
1919 |
1920 |
1921 |
1922 |
1923 |
1924 |
1925 |
1926 |
1927 |
1928 |
1929 |
1930 |
1931 |
1932 |
1933 |
1934 |
1935 |
1936 |
1937 |
1938 |
1939 |
1940 |
1941 |
1942 |
1943 |
1944 |
1945 |
1946 |
1947 |
1948 |
1949 |
1950 |
1951 |
1952 |
1953 |
1954 |
1955 |
1956 |
1957 |
1958 |
1959 |
1960 |
1961 |
1962 |
1963 |
1964 |
1965 |
1966 |
1967 |
1968 |
1969 |
1970 |
1971 |
1972 |
1973 |
1974 |
1975 |
1976 |
1977 |
1978 |
1979 |
1980 |
1981 |
1982 |
1983 |
1984 |
1985 |
1986 |
1987 |
1988 |
1989 |
1990 |
1991 |
1992 |
1993 |
1994 |
1995 |
1996 |
1997 |
1998 |
1999 |
2000 |
2001 |
2002 |
2003 |
2004 |
2005 |
2006 |
2007 |
2008 |
2009 |
2010 |
2011 |
2012 |
2013 |
2014 |
2015 |
2016 |
2017 |
2018 |
2019 |
2020 |
2021 |
2022 |
2023 |
2024 |
2025 |
2026 |
2027 |
2028 |
2029 |
2030 |
2031 |
2032 |
2033 |
2034 |
2035 |
2036 |
2037 |
2038 |
2039 |
2040 |
2041 |
2042 |
2043 |
2044 |
2045 |
2046 |
2047 |
2048 |
2049 |
2050 |
2051 |
2052 |
2053 |
2054 |
2055 |
2056 |
2057 |
2058 |
2059 |
2060 |
2061 |
2062 |
2063 |
2064 |
2065 |
2066 |
2067 |
2068 |
2069 |
2070 |
2071 |
2072 |
2073 |
2074 |
2075 |
2076 |
2077 |
2078 |
2079 |
2080 |
2081 |
2082 |
2083 |
2084 |
2085 |
2086 |
2087 |
2088 |
2089 |
2090 |
2091 |
2092 |
2093 |
2094 |
2095 |
2096 |
2097 |
2098 |
2099 |
2100 |
2101 |
2102 |
2103 |
2104 |
2105 |
2106 |
2107 |
2108 |
2109 |
2110 |
2111 |
2112 |
2113 |
2114 |
2115 |
2116 |
2117 |
2118 |
2119 |
2120 |
2121 |
2122 |
2123 |
2124 |
2125 |
2126 |
2127 |
2128 |
2129 |
2130 |
2131 |
2132 |
2133 |
2134 |
2135 |
2136 |
2137 |
2138 |
2139 |
2140 |
2141 |
2142 |
2143 |
2144 |
2145 |
2146 |
2147 |
2148 |
2149 |
2150 |
2151 |
2152 |
2153 |
2154 |
2155 |
2156 |
2157 |
2158 |
2159 |
2160 |
2161 |
2162 |
2163 |
2164 |
2165 |
2166 |
2167 |
2168 |
2169 |
2170 |
2171 |
2172 |
2173 |
2174 |
2175 |
2176 |
2177 |
2178 |
2179 |
2180 |
2181 |
2182 |
2183 |
2184 |
2185 |
2186 |
2187 |
2188 |
2189 |
2190 |
2191 |
2192 |
2193 |
2194 |
2195 |
2196 |
2197 |
2198 |
2199 |
2200 |
2201 |
2202 |
2203 |
2204 |
2205 |
2206 |
2207 |
2208 |
2209 |
2210 |
2211 |
2212 |
2213 |
2214 |
2215 |
2216 |
2217 |
2218 |
2219 |
2220 |
2221 |
2222 |
2223 |
2224 |
2225 |
2226 |
2227 |
2228 |
2229 |
2230 |
2231 |
2232 |
2233 |
2234 |
2235 |
2236 |
2237 |
2238 |
2239 |
2240 |
2241 |
2242 |
2243 |
2244 |
2245 |
2246 |
2247 |
2248 |
2249 |
2250 |
2251 |
2252 |
2253 |
2254 |
2255 |
2256 |
2257 |
2258 |
2259 |
2260 |
2261 |
2262 |
2263 |
2264 |
2265 |
2266 |
2267 |
2268 |
2269 |
2270 |
2271 |
2272 |
2273 |
2274 |
2275 |
2276 |
2277 |
2278 |
2279 |
2280 |
2281 |
2282 |
2283 |
2284 |
2285 |
2286 |
2287 |
2288 |
2289 |
2290 |
2291 |
2292 |
2293 |
2294 |
2295 |
2296 |
2297 |
2298 |
2299 |
2300 |
2301 |
2302 |
2303 |
2304 |
2305 |
2306 |
2307 |
2308 |
2309 |
2310 |
2311 |
2312 |
2313 |
2314 |
2315 |
2316 |
2317 |
2318 |
2319 |
2320 |
2321 |
2322 |
2323 |
2324 |
2325 |
2326 |
2327 |
2328 |
2329 |
2330 |
2331 |
2332 |
2333 |
2334 |
2335 |
2336 |
2337 |
2338 |
2339 |
2340 |
2341 |
2342 |
2343 |
2344 |
2345 |
2346 |
2347 |
2348 |
2349 |
2350 |
2351 |
2352 |
2353 |
2354 |
2355 |
2356 |
2357 |
2358 |
2359 |
2360 |
2361 |
2362 |
2363 |
2364 |
2365 |
2366 |
2367 |
2368 |
2369 |
2370 |
2371 |
2372 |
2373 |
2374 |
2375 |
2376 |
2377 |
2378 |
2379 |
2380 |
2381 |
2382 |
2383 |
2384 |
2385 |
2386 |
2387 |
2388 |
2389 |
2390 |
2391 |
2392 |
2393 |
2394 |
2395 |
2396 |
2397 |
2398 |
2399 |
2400 |
2401 |
2402 |
2403 |
2404 |
2405 |
2406 |
2407 |
2408 |
2409 |
2410 |
2411 |
2412 |
2413 |
2414 |
2415 |
2416 |
2417 |
2418 |
2419 |
2420 |
2421 |
2422 |
2423 |
2424 |
2425 |
2426 |
2427 |
2428 |
2429 |
2430 |
2431 |
2432 |
2433 |
2434 |
2435 |
2436 |
2437 |
2438 |
2439 |
2440 |
2441 |
2442 |
2443 |
2444 |
2445 |
2446 |
2447 |
2448 |
2449 |
2450 |
2451 |
2452 |
2453 |
2454 |
2455 |
2456 |
2457 |
2458 |
2459 |
2460 |
2461 |
2462 |
2463 |
2464 |
2465 |
2466 |
2467 |
2468 |
2469 |
2470 |
2471 |
2472 |
2473 |
2474 |
2475 |
2476 |
2477 |
2478 |
2479 |
2480 |
2481 |
2482 |
2483 |
2484 |
2485 |
2486 |
2487 |
2488 |
2489 |
2490 |
2491 |
2492 |
2493 |
2494 |
2495 |
2496 |
2497 |
2498 |
2499 |
2500 |
2501 |
2502 |
2503 |
2504 |
2505 |
2506 |
2507 |
2508 |
2509 |
2510 |
2511 |
2512 |
2513 |
2514 |
2515 |
2516 |
2517 |
2518 |
2519 |
2520 |
2521 |
2522 |
2523 |
2524 |
2525 |
2526 |
2527 |
2528 |
2529 |
2530 |
2531 |
2532 |
2533 |
2534 |
2535 |
2536 |
2537 |
2538 |
2539 |
2540 |
2541 |
2542 |
2543 |
2544 |
2545 |
2546 |
2547 |
2548 |
2549 |
2550 |
2551 |
2552 |
2553 |
2554 |
2555 |
2556 |
2557 |
2558 |
2559 |
2560 |
2561 |
2562 |
2563 |
2564 |
2565 |
2566 |
2567 |
2568 |
2569 |
2570 |
2571 |
2572 |
2573 |
2574 |
2575 |
2576 |
2577 |
2578 |
2579 |
2580 |
2581 |
2582 |
2583 |
2584 |
2585 |
2586 |
2587 |
2588 |
2589 |
2590 |
2591 |
2592 |
2593 |
2594 |
2595 |
2596 |
2597 |
2598 |
2599 |
2600 |
2601 |
2602 |
2603 |
2604 |
2605 |
2606 |
2607 |
2608 |
2609 |
2610 |
2611 |
2612 |
2613 |
2614 |
2615 |
2616 |
2617 |
2618 |
2619 |
2620 |
2621 |
2622 |
2623 |
2624 |
2625 |
2626 |
2627 |
2628 |
2629 |
2630 |
2631 |
2632 |
2633 |
2634 |
2635 |
2636 |
2637 |
2638 |
2639 |
2640 |
2641 |
2642 |
2643 |
2644 |
2645 |
2646 |
2647 |
2648 |
2649 |
2650 |
2651 |
2652 |
2653 |
2654 |
2655 |
2656 |
2657 |
2658 |
2659 |
2660 |
2661 |
2662 |
2663 |
2664 |
2665 |
2666 |
2667 |
2668 |
2669 |
2670 |
2671 |
2672 |
2673 |
2674 |
2675 |
2676 |
2677 |
2678 |
2679 |
2680 |
2681 |
2682 |
2683 |
2684 |
2685 |
2686 |
2687 |
2688 |
2689 |
2690 |
2691 |
2692 |
2693 |
2694 |
2695 |
2696 |
2697 |
2698 |
2699 |
2700 |
2701 |
2702 |
2703 |
2704 |
2705 |
2706 |
2707 |
2708 |
2709 |
2710 |
2711 |
2712 |
2713 |
2714 |
2715 |
2716 |
2717 |
2718 |
2719 |
2720 |
2721 |
2722 |
2723 |
2724 |
2725 |
2726 |
2727 |
2728 |
2729 |
2730 |
2731 |
2732 |
2733 |
2734 |
2735 |
2736 |
2737 |
2738 |
2739 |
2740 |
2741 |
2742 |
2743 |
2744 |
2745 |
2746 |
2747 |
2748 |
2749 |
2750 |
2751 |
2752 |
2753 |
2754 |
2755 |
2756 |
2757 |
2758 |
2759 |
2760 |
2761 |
2762 |
2763 |
2764 |
2765 |
2766 |
2767 |
2768 |
2769 |
2770 |
2771 |
2772 |
2773 |
2774 |
2775 |
2776 |
2777 |
2778 |
2779 |
2780 |
2781 |
2782 |
2783 |
2784 |
2785 |
2786 |
2787 |
2788 |
2789 |
2790 |
2791 |
2792 |
2793 |
2794 |
2795 |
2796 |
2797 |
2798 |
2799 |
2800 |
2801 |
2802 |
2803 |
2804 |
2805 |
2806 |
2807 |
2808 |
2809 |
2810 |
2811 |
2812 |
2813 |
2814 |
2815 |
2816 |
2817 |
2818 |
2819 |
2820 |
2821 |
2822 |
2823 |
2824 |
2825 |
2826 |
2827 |
2828 |
2829 |
2830 |
2831 |
2832 |
2833 |
2834 |
2835 |
2836 |
2837 |
2838 |
2839 |
2840 |
2841 |
2842 |
2843 |
2844 |
2845 |
2846 |
2847 |
2848 |
2849 |
2850 |
2851 |
2852 |
2853 |
2854 |
2855 |
2856 |
2857 |
2858 |
2859 |
2860 |
2861 |
2862 |
2863 |
2864 |
2865 |
2866 |
2867 |
2868 |
2869 |
2870 |
2871 |
2872 |
2873 |
2874 |
2875 |
2876 |
2877 |
2878 |
2879 |
2880 |
2881 |
2882 |
2883 |
2884 |
2885 |
2886 |
2887 |
2888 |
2889 |
2890 |
2891 |
2892 |
2893 |
2894 |
2895 |
2896 |
2897 |
2898 |
2899 | #endif // DETOURS_ARM
2900 |
2901 | //
2902 | ///////////////////////////////////////////////////////////////// End of File.
2903 |
--------------------------------------------------------------------------------