aboutsummaryrefslogtreecommitdiffhomepage
path: root/ext/detours/samples/disas/disas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ext/detours/samples/disas/disas.cpp')
-rw-r--r--ext/detours/samples/disas/disas.cpp702
1 files changed, 702 insertions, 0 deletions
diff --git a/ext/detours/samples/disas/disas.cpp b/ext/detours/samples/disas/disas.cpp
new file mode 100644
index 0000000..db8ef6a
--- /dev/null
+++ b/ext/detours/samples/disas/disas.cpp
@@ -0,0 +1,702 @@
+/////////////////////////////////////////////////////////////////////////////
+//
+// Module: disas.cpp (disas.exe - Detours Test Program)
+//
+// Microsoft Research Detours Package
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+
+#define DETOURS_INTERNAL
+#include <detours.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+///////////////////////////////////////////////////////////////////////// ARM.
+//
+#ifdef DETOURS_ARM
+
+extern "C" BYTE TestCodes[];
+
+void DumpMemoryFragment(PBYTE pbData, ULONG cbData, ULONG cbSpace)
+{
+ ULONG n = 0;
+ if (cbData >= 4) {
+ printf("%04x%04x ", ((PUSHORT)pbData)[0], ((PUSHORT)pbData)[1]);
+ n += 4;
+ }
+ else if (cbData >= 2) {
+ printf("%04x ", *((PUSHORT)pbData));
+ n += 2;
+ }
+
+ for (; n < cbSpace; n++) {
+ if (n < cbData) {
+ printf("%02x", pbData[n]);
+ }
+ else {
+ printf(" ");
+ }
+ }
+ if (n < cbData) {
+ printf(".");
+ }
+ else {
+ printf(" ");
+ }
+}
+
+inline ULONG fetch_thumb_opcode(PBYTE pbCode)
+{
+ ULONG Opcode = *(UINT16 *)&pbCode[0];
+ if (Opcode >= 0xe800) {
+ Opcode = (Opcode << 16) | *(UINT16 *)&pbCode[2];
+ }
+ return Opcode;
+}
+
+BOOL IsTerminate(PBYTE pbSrc)
+{
+ ULONG opcode = fetch_thumb_opcode(pbSrc);
+
+ if ((opcode & 0xff87) == 0x4700) {
+ // bx r
+ return TRUE;
+ }
+
+#if 0
+ if ((opcode & 0xfbf08f00) == 0xf2400c00) { // movw r12,#xxxx
+ return TRUE;
+ }
+
+ if ((opcode == 0xf8dcf000) { // ldr pc,[r12]
+ ULONG Immediate = ((opcode2 << 12) & 0xf7000000) |
+ ((opcode2 << 1) & 0x08000000) |
+ ((opcode2 << 16) & 0x00ff0000) |
+ ((opcode >> 4) & 0x0000f700) |
+ ((opcode >> 15) & 0x00000800) |
+ ((opcode >> 0) & 0x000000ff);
+ PBYTE pbTarget = *(PBYTE *)Immediate;
+ if (detour_is_imported(pbCode, pbTarget)) {
+ PBYTE pbNew = *(PBYTE *)pbTarget;
+ DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew));
+ return pbNew;
+ }
+ }
+ }
+ }
+#endif
+
+ return FALSE;
+}
+
+#endif // DETOURS_ARM
+
+///////////////////////////////////////////////////////////////// X86 and X64.
+//
+#if defined(DETOURS_X86) || defined(DETOURS_X64)
+
+extern "C" BYTE TestCodes[];
+
+void DumpMemoryFragment(PBYTE pbData, ULONG cbData, ULONG cbSpace)
+{
+ ULONG n = 0;
+ for (; n < cbSpace; n++) {
+ if (n < cbData) {
+ printf("%02x", pbData[n]);
+ }
+ else {
+ printf(" ");
+ }
+ }
+ if (n < cbData) {
+ printf(".");
+ }
+ else {
+ printf(" ");
+ }
+}
+
+BOOL IsTerminate(PBYTE pbSrc)
+{
+ if ((0xC3 == pbSrc[0] && 0x00 == pbSrc[1]) || // bx lr
+ 0xCB == pbSrc[0] || // RETF
+ 0xC2 == pbSrc[0] || // RET dw
+ 0xCA == pbSrc[0] || // RETF dw
+ 0xEB == pbSrc[0] || // JMP ob
+ 0xE9 == pbSrc[0] || // JMP ol
+ 0xEA == pbSrc[0]) { // JMP ol
+
+ return TRUE;
+ }
+ if (0xff == pbSrc[0] && 0x25 == pbSrc[1]) // JMP [addr]
+ return TRUE;
+ return FALSE;
+}
+
+#endif // DETOURS_X86 || DETOURS_X64
+
+/////////////////////////////////////////////////////////// X86, X64, and ARM.
+//
+#if defined(DETOURS_X86) || defined(DETOURS_X64) || defined(DETOURS_ARM)
+struct BasicBlockLink
+{
+ public:
+ BasicBlockLink * m_pNext;
+ PBYTE m_pbEntry;
+ PCHAR m_pszName;
+
+ public:
+ BasicBlockLink(PBYTE pbEntry, PCHAR pszName = NULL)
+ {
+ m_pNext = NULL;
+ m_pbEntry = pbEntry;
+ m_pszName = pszName;
+
+ *s_ppTail = this;
+ s_ppTail = &m_pNext;
+ }
+
+ BasicBlockLink * Next()
+ {
+ return m_pNext;
+ }
+
+ static BasicBlockLink * GetListHead()
+ {
+ return s_pHead;
+ }
+
+ protected:
+ static BasicBlockLink * s_pHead;
+ static BasicBlockLink ** s_ppTail;
+};
+
+BasicBlockLink * BasicBlockLink::s_pHead = NULL;
+BasicBlockLink ** BasicBlockLink::s_ppTail = &BasicBlockLink::s_pHead;
+
+static PBYTE s_pbBegin = NULL;
+static PBYTE s_pbLimit = NULL;
+
+int TestDetourCopyInstruction(PBYTE pbSrcInstruction, PCHAR pszFunction)
+{
+ PBYTE pbSrc = pbSrcInstruction;
+ ULONG nIns = 0;
+
+ if (pszFunction) {
+ printf("%s:\n", pszFunction);
+ }
+ for (; nIns < 4096; nIns++) {
+ BYTE rbDst[128];
+ PVOID pbDstPool = (PVOID)(rbDst + sizeof(rbDst));
+ LONG lExtra = 0;
+ PVOID pbTarget = NULL;
+ ULONG cbStep = (ULONG)((PBYTE)DetourCopyInstruction(rbDst, &pbDstPool, pbSrc,
+ &pbTarget, &lExtra) - pbSrc);
+
+ printf(" %p:", pbSrc);
+ DumpMemoryFragment(rbDst, cbStep, 10);
+ printf(" ");
+ DumpMemoryFragment(rbDst, cbStep, 10);
+ if (pbTarget) {
+ if (pbTarget == DETOUR_INSTRUCTION_TARGET_DYNAMIC) {
+ printf(" Dynamic\n");
+ }
+ else {
+ printf(" %p%c\n", pbTarget,
+ (pbTarget >= s_pbBegin && pbTarget < s_pbLimit) ? ' ' : '!');
+ }
+ }
+ else {
+ printf("\n");
+ }
+
+ if (pbTarget && pbTarget != DETOUR_INSTRUCTION_TARGET_DYNAMIC) {
+ if (pbTarget > pbSrc &&
+ pbTarget >= s_pbBegin &&
+ pbTarget < s_pbLimit
+ ) {
+ (void) new BasicBlockLink((PBYTE)pbTarget, NULL);
+ }
+ }
+
+ if (IsTerminate(pbSrc)) {
+ break;
+ }
+
+ pbSrc += cbStep;
+ }
+ return nIns;
+}
+
+BOOL CALLBACK ExportCallback(_In_opt_ PVOID pContext,
+ _In_ ULONG nOrdinal,
+ _In_opt_ LPCSTR pszName,
+ _In_opt_ PVOID pCode)
+{
+ (void)pContext;
+ (void)nOrdinal;
+ (void)pCode;
+
+ (VOID) new BasicBlockLink((PBYTE)pCode, pszName ? pszName : "[NO NAME]");
+ return TRUE;
+}
+#endif // DETOURS_X86 || DETOURS_X64
+
+//////////////////////////////////////////////////////////////////////// IA64.
+//
+#ifdef DETOURS_IA64
+#pragma warning(disable: 4201) // ignore warning about unnamed sturcture in union.
+
+void DumpHi(PBYTE pbData, ULONG cbData, ULONG cbSpace)
+{
+ ULONG n = 0;
+ for (; n < cbSpace; n++) {
+ if (n < cbData) {
+ printf("%02x", pbData[(cbData - 1) - n]);
+ }
+ else {
+ printf(" ");
+ }
+ }
+ printf("\n");
+}
+
+struct DETOUR_IA64_BUNDLE_DISASSEMBLE : public DETOUR_IA64_BUNDLE
+{
+ public:
+ void SetBrx(UINT64 raw)
+ {
+ SetBrl();
+ SetBrlImm(raw);
+ }
+
+ void Dis()
+ {
+ const char szUnitNames[17] = "?aimbflx?AIMBFLX";
+
+ printf("%p: ", data);
+ BYTE nTemplate = GetTemplate();
+ BYTE nInst0 = GetInst0();
+ BYTE nInst1 = GetInst1();
+ BYTE nInst2 = GetInst2();
+ BYTE nUnit0 = GetUnit0();
+ BYTE nUnit1 = GetUnit1();
+ BYTE nUnit2 = GetUnit2();
+ if (nUnit1 == L_UNIT) { // MLX instruction
+ UINT64 d2 = (
+ // 0x0000000000fffff0
+ ((wide[1] & 0x00fffff000000000) >> 32) |
+ // 0x000000ffff000000
+ ((wide[0] & 0xffff000000000000) >> 24) |
+ // 0x7fffff0000000000
+ ((wide[1] & 0x00000000007fffff) << 40) |
+ // 0x8000000000000000
+ ((wide[1] & 0x0800000000000000) << 4)
+ );
+ printf("%02x %c%01x %010I64lx %c%01x %016I64lx",
+ nTemplate,
+ szUnitNames[nUnit0], nInst0, GetData0(),
+ szUnitNames[nUnit2], nInst2, d2);
+ }
+ else {
+ printf("%02x %c%01x %010I64lx %c%01x %010I64lx %c%01x %010I64lx",
+ nTemplate,
+ szUnitNames[nUnit0], nInst0, GetData0(),
+ szUnitNames[nUnit1], nInst1, GetData1(),
+ szUnitNames[nUnit2], nInst2, GetData2());
+ }
+
+ if (IsBrl()) {
+ printf(" brl %p", GetBrlTarget());
+ }
+ else if (IsMovlGp()) {
+ printf(" movl gp=%p", GetMovlGp());
+ }
+ if ((wide[0] & 0xfffffc000603ffff) == 0x002024000200100b &&
+ wide[1] == 0x0004000000203008) {
+
+ ULONG64 offset =
+ ((wide[0] & 0x0000000001fc0000) >> 18) | // imm7b
+ ((wide[0] & 0x000001ff00000000) >> 25) | // imm9d
+ ((wide[0] & 0x00000000f8000000) >> 11); // imm5c
+ if (wide[0] & 0x0000020000000000) {
+ offset |= 0xffffffffffe00000;
+ }
+ printf(" imm=%016I64lx", offset);
+ }
+ printf("\n");
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+//
+BOOL CALLBACK ExportCallbackIA64(_In_opt_ PVOID pContext,
+ _In_ ULONG nOrdinal,
+ _In_opt_ LPCSTR pszName,
+ _In_opt_ PVOID pCode)
+{
+ (void)pContext;
+ (void)nOrdinal;
+
+ DETOUR_IA64_BUNDLE_DISASSEMBLE *pb = *(DETOUR_IA64_BUNDLE_DISASSEMBLE **)pCode;
+ DETOUR_IA64_BUNDLE temp;
+
+ if (!pb[0].Copy(&temp)) {
+ printf("%s:\n ", pszName ? pszName : "[NO NAME]");
+ pb[0].Dis();
+ }
+ return TRUE;
+}
+
+#if 0
+void TestBoth()
+{
+ LPVOID pvBase = VirtualAlloc((PBYTE)0x800000000, 0x10000,
+ MEM_RESERVE | MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+
+ DETOUR_IA64_BUNDLE *pbBase = (DETOUR_IA64_BUNDLE *)pvBase;
+ DETOUR_IA64_BUNDLE *pb = pbBase;
+
+ printf("TestBoth:\n");
+ for (UINT64 i = 0x10; i < 0x8000000000000000; i <<= 1) {
+ pb->SetMovlGp(i);
+ if (pb->GetMovlGp() != i) {
+ printf("Error in MovlGp!\n");
+ return;
+ }
+ pb++;
+
+ pb->SetBrl(i);
+ if (pb->GetBrlEip() != i) {
+ printf("Error in Brl!\n");
+ return;
+ }
+ pb++;
+ }
+
+ for (UINT64 i = (UINT64)(INT64)-0x10; i > 0; i <<= 1) {
+ pb->SetMovlGp(i);
+ if (pb->GetMovlGp() != i) {
+ printf("Error in MovlGp!\n");
+ return;
+ }
+ pb++;
+
+ pb->SetBrl(i);
+ if (pb->GetBrlEip() != i) {
+ printf("Error in Brl!\n");
+ return;
+ }
+ pb++;
+ }
+
+ printf("u %p %p\n", pbBase, pb);
+}
+#endif
+#endif // DETOURS_IA64
+
+int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmdShow)
+{
+ (void)hprev;
+ (void)hinst;
+ (void)lpszCmdLine;
+ (void)nCmdShow;
+
+ // Bug report, but it works here.
+ // 07ff8`4b783054 49ba 70b3d93a d40fb998 mov r10,98B90FD43AD9B370h
+ //
+ {
+ static const UCHAR mov_r10_imm64[] = {0x49, 0xba, 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ PVOID const after = DetourCopyInstructionX64(0, 0, const_cast<PUCHAR>(mov_r10_imm64), 0, 0);
+
+ if (after != &mov_r10_imm64 + 1)
+ {
+ printf("mov_r10_imm64 failed, expected:%p vs. got:%p\n", &mov_r10_imm64 + 1, after);
+ if (IsDebuggerPresent())
+ {
+ __debugbreak();
+ DetourCopyInstructionX64(0, 0, const_cast<PUCHAR>(mov_r10_imm64), 0, 0);
+ }
+ return 1;
+ }
+ }
+
+#ifdef DETOURS_IA64
+ // First we check the pre-canned TestCodes from disasm.asm
+ //
+ PBYTE pbTest = *(PBYTE*)WinMain;
+ for (;; pbTest += 16) {
+ DETOUR_IA64_BUNDLE_DISASSEMBLE *pb = (DETOUR_IA64_BUNDLE_DISASSEMBLE *)pbTest;
+
+ pb->Dis();
+ if (pbTest[0] == 0xff) {
+ break;
+ }
+ DumpHi(pbTest, 16, 16);
+ }
+
+#if 0
+ printf("\n\n");
+
+ DETOUR_IA64_BUNDLE_DISASSEMBLE *pb = (DETOUR_IA64_BUNDLE_DISASSEMBLE *)pbTest;
+ DETOUR_IA64_BUNDLE_DISASSEMBLE *pbBeg = pb;
+ DWORD dwOld;
+ VirtualProtect(pb, 0x2000, PAGE_EXECUTE_READWRITE, &dwOld);
+ printf("%p: (%d)\n", pb, sizeof(pb));
+ pb++;
+ printf("%p: (%d)\n", pb, sizeof(pb));
+ pb++; pb->SetBrx(0);
+ pb++; pb->SetBrx(0);
+ pb++; pb->SetBrx(0);
+ pb++; pb->SetBrx(0xffffffffffffffff);
+ pb++; pb->SetBrx(0x0fffffffffffffff);
+ pb++; pb->SetBrx(0x00ffffffffffffff);
+ pb++; pb->SetBrx(0x000fffffffffffff);
+ pb++; pb->SetBrx(0x0000ffffffffffff);
+ pb++; pb->SetBrx(0x00000fffffffffff);
+ pb++; pb->SetBrx(0x000000ffffffffff);
+ pb++; pb->SetBrx(0x0000000fffffffff);
+ pb++; pb->SetBrx(0x00000000ffffffff);
+ pb++; pb->SetBrx(0x000000000fffffff);
+ pb++; pb->SetBrx(0x0000000000ffffff);
+ pb++; pb->SetBrx(0x00000000000fffff);
+ pb++; pb->SetBrx(0x000000000000ffff);
+ pb++; pb->SetBrx(0x0000000000000fff);
+ pb++; pb->SetBrx(0x00000000000000ff);
+ pb++; pb->SetBrx(0x000000000000000f);
+ pb++; pb->SetBrx(0x0000000000000000);
+ pb++; pb->SetBrx(0xffffffffffffffff);
+ pb++; pb->SetBrx(0xffffffffffffffff);
+ pb->SetInst0(0xff);
+ pb->SetData0(0xffffffffffffffff);
+ printf("%p:\n", pb);
+ DETOUR_IA64_BUNDLE_DISASSEMBLE *pbEnd = pb;
+ for (pb = pbBeg; pb < pbEnd; pb++) {
+ printf(" %p: ", pb);
+ DumpHi((BYTE*)pb, 16, 16);
+ }
+#endif
+
+#if 1
+ {
+ // Then we check all of the code we can find in user32.dll
+ //
+ printf("\n");
+ HINSTANCE hInst = LoadLibraryA("user32.dll");
+ printf("Loaded: user32.dll: %p\n", hInst);
+
+ PBYTE pbEntry = (PBYTE)DetourGetEntryPoint(hInst);
+ printf("Entry: %p\n", pbEntry);
+ ExportCallbackIA64(NULL, 0, "[Entry]", pbEntry);
+ DetourEnumerateExports(hInst, NULL, ExportCallbackIA64);
+ }
+
+ {
+ // Then we check all of the code we can find in opengl32.dll
+ //
+ printf("\n");
+ HINSTANCE hInst = LoadLibraryA("opengl32.dll");
+ printf("Loaded: opengl32.dll: %p\n", hInst);
+
+ PBYTE pbEntry = (PBYTE)DetourGetEntryPoint(hInst);
+ printf("Entry: %p\n", pbEntry);
+ ExportCallbackIA64(NULL, 0, "[Entry]", pbEntry);
+ DetourEnumerateExports(hInst, NULL, ExportCallbackIA64);
+ }
+
+ printf("\n");
+ for (HINSTANCE hInst = NULL; (hInst = DetourEnumerateModules(hInst)) != NULL;) {
+ CHAR szModuleName[512];
+ GetModuleFileNameA(hInst, szModuleName,
+ sizeof(szModuleName)/sizeof(szModuleName[0]));
+ printf("%p : %s\n", hInst, szModuleName);
+ DetourEnumerateExports(hInst, NULL, ExportCallbackIA64);
+ }
+
+ printf("\n");
+#endif
+#if 0
+ TestBoth();
+#endif
+#endif // DETOURS_IA64
+
+#if defined(DETOURS_X64) || defined(DETOURS_X86)
+ // First we check the pre-canned TestCodes from disasm.asm
+ //
+ PBYTE pbBegin = (PBYTE)DetourCodeFromPointer(TestCodes, NULL);
+ printf("%p:\n", pbBegin);
+ for (PBYTE pbTest = pbBegin;;) {
+ if (pbTest[0] != 0xcc) { // int 3
+ printf("%08lx ", (ULONG)(pbTest - pbBegin));
+ DumpMemoryFragment(pbTest, 8, 8);
+ printf("\n");
+ printf("failed on last.\n");
+ return 1;
+ }
+ pbTest++;
+
+ if (pbTest[0] == 0x70 || pbTest[0] == 0x71) {
+ printf("[%p]:\n", pbTest);
+ }
+ BYTE rbDst[128];
+ PVOID pbDstPool = (PVOID)(rbDst + sizeof(rbDst));
+ LONG lExtra = 0;
+ PVOID pbTarget = NULL;
+ PBYTE pbNext = (PBYTE)DetourCopyInstruction(rbDst, &pbDstPool, pbTest,
+ &pbTarget, &lExtra);
+
+ LONG cbTest = (LONG)(pbNext - pbTest);
+
+ printf("%08lx ", (ULONG)(pbTest - pbBegin));
+ DumpMemoryFragment(pbTest, cbTest, 12);
+ printf("[%16p] ", pbTarget);
+ DumpMemoryFragment(rbDst, cbTest + lExtra, 11);
+ printf("\n");
+
+ if (pbTest[cbTest] != 0xcc) {
+ printf("failed!\n");
+ return 1;
+ }
+
+ pbTest += cbTest;
+
+ if (pbTest[0] == 0xcc && pbTest[1] == 0xcc) {
+ break;
+ }
+ }
+
+#if 0
+ // Then we check all of the code we can find in user32.dll
+ //
+ HINSTANCE hInst = LoadLibraryA("user32.dll");
+ printf("Loaded: user32.dll: %p\n", hInst);
+
+ s_pbBegin = (PBYTE)hInst;
+ s_pbLimit = s_pbBegin + DetourGetModuleSize(hInst);
+
+ PBYTE pbEntry = DetourGetEntryPoint(hInst);
+ (VOID) new BasicBlockLink(pbEntry, "user32.dll");
+
+ DetourEnumerateExports(hInst, NULL, ExportCallback);
+
+ ULONG nIns = 0;
+ for (BasicBlockLink *pLink = BasicBlockLink::GetListHead();
+ pLink; pLink = pLink->Next()) {
+
+ nIns += TestDetourCopyInstruction(pLink->m_pbEntry, pLink->m_pszName);
+ if (nIns > 100000) {
+ break;
+ }
+ }
+ printf("Disassembled %d instructions.\n", nIns);
+#endif
+#endif // DETOURS_X86 || DETOURS_X64
+
+#ifdef DETOURS_ARM
+ // Create an output buffer and fill it with debugbreaks.
+ //
+ PBYTE pbBuffer
+ = (PBYTE)VirtualAlloc(NULL, 0x400, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ for (PBYTE pbOut = pbBuffer; pbOut < pbBuffer + 0x400;) {
+ *pbOut++ = 0xfe;
+ *pbOut++ = 0xde;
+ }
+ PBYTE pbDst = pbBuffer;
+ PVOID pvDstPool = (PVOID)(pbBuffer + 0x400);
+
+ // First we check the pre-canned TestCodes from disasm.asm
+ //
+ PBYTE pbBegin = (PBYTE)DetourCodeFromPointer(TestCodes, NULL);
+ printf("%p: (TestCodes %p) => %p\n", pbBegin, TestCodes, pbBuffer);
+ for (PBYTE pbSrc = pbBegin;;) {
+ if (pbSrc[0] != 0xfe && pbSrc[1] != 0xde) { // BREAK
+ printf("%08x ", pbSrc - pbBegin);
+ DumpMemoryFragment(pbSrc, 8, 8);
+ printf("\n");
+ printf("failed on last.\n");
+ return 1;
+ }
+ pbSrc += 2;
+ *pbDst++ = 0xfe;
+ *pbDst++ = 0xde;
+
+ if ((pbSrc[0] == 0x00 && pbSrc[1] == 0xbf) && // NOP
+ (pbSrc[2] != 0xfe && pbSrc[3] != 0xde)) { // BREAK
+ // Skip over a single NOP so we can test alignment.
+ pbSrc += 2;
+ }
+
+ if ((pbSrc[0] == 0x00 && pbSrc[1] == 0xbf) && // NOP
+ (pbSrc[2] != 0xfe && pbSrc[3] != 0xde)) { // BREAK
+ // If there is a second NOP, then we insert alignment.
+ pbSrc += 2;
+ *pbDst++ = 0x00;
+ *pbDst++ = 0xbf;
+ }
+
+
+ LONG lExtra = 0;
+ PVOID pbTarget = NULL;
+ PBYTE pbNext = (PBYTE)DetourCopyInstruction(pbDst, &pvDstPool, pbSrc, &pbTarget, &lExtra);
+
+ LONG cbTest = (LONG)(pbNext - pbSrc);
+
+ printf("%08x ", pbSrc - pbBegin);
+ DumpMemoryFragment(pbSrc, cbTest, 4);
+ printf("[%8p] ", pbTarget);
+ DumpMemoryFragment(pbDst, cbTest + lExtra, 16);
+ printf("\n");
+
+ if (pbSrc[cbTest] != 0xfe || pbSrc[cbTest+1] != 0xde) {
+ printf("%p: failed! (pbSrc[n]=%02x, pbSrc[n+1]=%02x\n",
+ pbSrc,
+ pbSrc[cbTest], pbSrc[cbTest+1]);
+ __debugbreak();
+ pbNext = (PBYTE)DetourCopyInstruction(pbDst, &pvDstPool, pbSrc, &pbTarget, &lExtra);
+ cbTest = (LONG)(pbNext - pbSrc);
+ return 1;
+ }
+
+ pbDst += cbTest + lExtra;
+ pbSrc += cbTest;
+
+ if (pbSrc[0] == 0xfe && pbSrc[1] == 0xde &&
+ pbSrc[2] == 0xfe && pbSrc[3] == 0xde) {
+ break;
+ }
+ }
+
+#if 0
+ // Then we check all of the code we can find in user32.dll
+ //
+ HINSTANCE hInst = LoadLibraryA("user32.dll");
+ printf("Loaded: user32.dll: %p\n", hInst);
+
+ s_pbBegin = (PBYTE)hInst;
+ s_pbLimit = s_pbBegin + DetourGetModuleSize(hInst);
+
+ PBYTE pbEntry = DetourGetEntryPoint(hInst);
+ (VOID) new BasicBlockLink(pbEntry, "user32.dll");
+
+ DetourEnumerateExports(hInst, NULL, ExportCallback);
+
+ ULONG nIns = 0;
+ for (BasicBlockLink *pLink = BasicBlockLink::GetListHead();
+ pLink; pLink = pLink->Next()) {
+
+ nIns += TestDetourCopyInstruction(pLink->m_pbEntry, pLink->m_pszName);
+ if (nIns > 100000) {
+ break;
+ }
+ }
+ printf("Disassembled %d instructions.\n", nIns);
+#endif
+#endif // DETOURS_ARM
+
+ return 0;
+}
+//
+///////////////////////////////////////////////////////////////// End of File.