VTHook.cpp
上传用户:kittypts
上传日期:2018-02-11
资源大小:241k
文件大小:4k
源码类别:

PlugIns编程

开发平台:

Visual C++

  1. /*
  2. *
  3. *  This file is
  4. *    Copyright (C) 2006-2008 Nektra S.A.
  5. *  
  6. *  This program is free software; you can redistribute it and/or modify
  7. *  it under the terms of the GNU Lesser General Public License as published by
  8. *  the Free Software Foundation; either version 2, or (at your option)
  9. *  any later version.
  10. *  
  11. *  This program is distributed in the hope that it will be useful,
  12. *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. *  GNU General Public License for more details.
  15. *  
  16. */
  17. #include "Memory.h"
  18. #include "VTHook.h"
  19. #include "Trampoline.h"
  20. ///
  21. /// EntryData
  22. ///
  23. struct NktVtHook::EntryData
  24. {
  25. DV_PTR prevAddress;
  26. DV_PTR index;
  27. DV_PTR pmsSize;
  28. NktTrampoline tramp;
  29. EntryData(USHORT cleanSize) : tramp(cleanSize) {}
  30. };
  31. ///
  32. /// Helpers:
  33. ///
  34. typedef void (__fastcall NktVtHook::* Method)(NktRegisters*, INT_PTR);
  35. typedef union {void* ptr; Method member; } method_ptr;
  36. ///
  37. /// Constructors / Destructor
  38. ///
  39. NktVtHook::NktVtHook(const DV_PTR vt, int cc)
  40. : _vt(vt), _cc(static_cast<NktCallingConvention>(cc)) { _ASSERT(cc == thiscall_ms_ || cc == thiscall_ || cc == thiscall_com_); }
  41. NktVtHook::~NktVtHook() {}
  42. ///
  43. /// CVTHook::HookEntry
  44. ///
  45. void NktVtHook::HookEntry(SIZE_T index, USHORT pmsSize)
  46. {
  47. //Check entry:
  48. if (_entries.find(index) != _entries.end())
  49. {
  50. OutputDebugStringW(L"VTHook: HookEntry: Entry already hooked.");
  51. return;
  52. }
  53. NktMemory mem(_vt);
  54. DV_PTR prev = 0;
  55. SIZE_T pos = index * sizeof(DV_PTR);
  56. //Obtain previous entry:
  57. mem.Read(pos, sizeof(DV_PTR), (DV_PTR)&prev);
  58. //Entry data:
  59. USHORT cleanSize = (_cc == thiscall_ms_)? pmsSize-/*pThis*/sizeof(DV_PTR) : pmsSize; //FIXME: support __fastcall
  60. EntryData* entry = new EntryData(cleanSize);
  61. entry->index = index;
  62. entry->prevAddress = prev;
  63. entry->pmsSize = (_cc == thiscall_ms_)? pmsSize - /*pThis*/sizeof(DV_PTR) : pmsSize;
  64. Entries::value_type v(index, entry);
  65. _entries.insert(v);
  66. //Init trampoline:
  67. NktTrampoline& tramp = entry->tramp;
  68. method_ptr member;
  69. member.member = &NktVtHook::InternalHandler;
  70. NktFunctionWrapper fh(member.ptr, fastcall_, REGISTER_SIZE << 1);
  71. tramp.SetTag((DV_PTR)entry);
  72. tramp.Initialize(fh, this);
  73. //Write new address:
  74. DV_PTR p = tramp.GetAddress();
  75. mem.Write(pos, sizeof(DV_PTR), &p);
  76. }
  77. ///
  78. /// CVTHook::GetAddress
  79. ///
  80. DV_PTR NktVtHook::GetAddress(SIZE_T index)
  81. {
  82. return _vt + index * sizeof(DV_PTR);
  83. }
  84. ///
  85. /// CVTHook::OldValue
  86. ///
  87. DV_PTR NktVtHook::GetOriginalAddress(SIZE_T index)
  88. {
  89. DV_PTR ret;
  90. Entries::iterator it = _entries.find(index);
  91. if (it != _entries.end())
  92. {
  93. EntryData* entry = it->second;
  94. ret = entry->prevAddress;
  95. }
  96. else
  97. ret = *((DV_PTR*)_vt + index);
  98. return ret;
  99. }
  100. ///
  101. /// CVTHook::UnhookEntry
  102. ///
  103. void NktVtHook::UnhookEntry(SIZE_T index /*= INVALID_INDEX*/)
  104. {
  105. //Restore all:
  106. Entries::iterator end = _entries.end();
  107. if (index == INVALID_INDEX)
  108. {
  109. for (Entries::const_iterator it = _entries.begin(); it != end; ++it)
  110. UnhookEntry(it->second);
  111. _entries.clear();
  112. }
  113. //Restore index
  114. else
  115. {
  116. Entries::iterator it = _entries.find(index);
  117. if (it == _entries.end())
  118. {
  119. WCHAR buffer[64];
  120. wsprintf(buffer, L"VTHook: RestoreEntry: Entry was not hooked: %i", index);
  121. OutputDebugStringW(buffer);
  122. return;
  123. }
  124. UnhookEntry(it->second);
  125. _entries.erase(it);
  126. }
  127. }
  128. void NktVtHook::UnhookEntry(EntryData* entry)
  129. {
  130. //Update VT and remove entry:
  131. SIZE_T pos = entry->index * sizeof(DV_PTR);
  132. NktMemory mem(_vt);
  133. DV_PTR prev = entry->prevAddress;
  134. mem.Write(pos, sizeof(DV_PTR), (DV_PTR)&prev);
  135. delete entry;
  136. }
  137. ///
  138. /// CHookBase::RawCallFunction [virtual]
  139. ///
  140. void NktVtHook::RawCallFunction(NktHookCallContext* ctx)
  141. {
  142. EntryData* entry = (EntryData*)ctx->tag;
  143. NktFunctionWrapper fw((void*)entry->prevAddress, _cc, entry->pmsSize);
  144. NktLocalFunction lf(fw);
  145. lf.Call(ctx->regs, ctx->pms, entry->pmsSize);
  146. }