1211
This commit is contained in:
48
test/Detours/samples/member/Makefile
Normal file
48
test/Detours/samples/member/Makefile
Normal file
@@ -0,0 +1,48 @@
|
||||
##############################################################################
|
||||
##
|
||||
## Makefile for Detours Test Programs.
|
||||
##
|
||||
## Microsoft Research Detours Package
|
||||
##
|
||||
## Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
##
|
||||
|
||||
!include ..\common.mak
|
||||
|
||||
LIBS=$(LIBS) kernel32.lib
|
||||
|
||||
all: dirs \
|
||||
$(BIND)\member.exe \
|
||||
!IF $(DETOURS_SOURCE_BROWSING)==1
|
||||
$(OBJD)\member.bsc
|
||||
!ENDIF
|
||||
|
||||
clean:
|
||||
-del *~ 2> nul
|
||||
-del $(BIND)\member.* 2> nul
|
||||
-rmdir /q /s $(OBJD) 2>nul
|
||||
|
||||
realclean: clean
|
||||
-rmdir /q /s $(OBJDS) 2>nul
|
||||
|
||||
dirs:
|
||||
@if not exist $(BIND) mkdir $(BIND) && echo. Created $(BIND)
|
||||
@if not exist $(OBJD) mkdir $(OBJD) && echo. Created $(OBJD)
|
||||
|
||||
$(OBJD)\member.obj : member.cpp
|
||||
|
||||
$(BIND)\member.exe : $(OBJD)\member.obj $(DEPS)
|
||||
cl $(CFLAGS) /Fe$@ /Fd$(@R).pdb $(OBJD)\member.obj \
|
||||
/link $(LINKFLAGS) $(LIBS) /subsystem:console
|
||||
|
||||
$(OBJD)\member.bsc : $(OBJD)\member.obj
|
||||
bscmake /v /n /o $@ $(OBJD)\member.sbr
|
||||
|
||||
##############################################################################
|
||||
|
||||
test: $(BIND)\member.exe
|
||||
@echo.
|
||||
$(BIND)\member.exe
|
||||
@echo.
|
||||
|
||||
################################################################# End of File.
|
||||
116
test/Detours/samples/member/member.cpp
Normal file
116
test/Detours/samples/member/member.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Test a detour of a member function (member.cpp of member.exe)
|
||||
//
|
||||
// Microsoft Research Detours Package
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// By default, C++ member functions use the __thiscall calling convention.
|
||||
// In order to Detour a member function, both the trampoline and the detour
|
||||
// must have exactly the same calling convention as the target function.
|
||||
// Unfortunately, the VC compiler does not support a __thiscall, so the only
|
||||
// way to create legal detour and trampoline functions is by making them
|
||||
// class members of a "detour" class.
|
||||
//
|
||||
// In addition, C++ does not support converting a pointer to a member
|
||||
// function to an arbitrary pointer. To get a raw pointer, the address of
|
||||
// the member function must be moved into a temporary member-function
|
||||
// pointer, then passed by taking it's address, then de-referencing it.
|
||||
// Fortunately, the compiler will optimize the code to remove the extra
|
||||
// pointer operations.
|
||||
//
|
||||
// If X::Target is a virtual function, the following code will *NOT* work
|
||||
// because &X::Target is the address of a thunk that does a virtual call,
|
||||
// not the real address of the X::Target. You can get the real address
|
||||
// of X::Target by looking directly in the VTBL for class X, but there
|
||||
// is no legal way to 1) get the address of X's VTBL or 2) get the offset
|
||||
// of ::Target within that VTBL. You can of course, figure these out for
|
||||
// a particular class and function, but there is no general way to do so.
|
||||
//
|
||||
#include <stdio.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <detours.h>
|
||||
|
||||
#include "..\slept\verify.cpp"
|
||||
|
||||
//////////////////////////////////////////////////////////////// Target Class.
|
||||
//
|
||||
class CMember
|
||||
{
|
||||
public:
|
||||
void Target(void);
|
||||
};
|
||||
|
||||
void CMember::Target(void)
|
||||
{
|
||||
printf(" CMember::Target! (this:%p)\n", this);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////// Detour Class.
|
||||
//
|
||||
class CDetour /* add ": public CMember" to enable access to member variables... */
|
||||
{
|
||||
public:
|
||||
void Mine_Target(void);
|
||||
static void (CDetour::* Real_Target)(void);
|
||||
|
||||
// Class shouldn't have any member variables or virtual functions.
|
||||
};
|
||||
|
||||
void CDetour::Mine_Target(void)
|
||||
{
|
||||
printf(" CDetour::Mine_Target! (this:%p)\n", this);
|
||||
(this->*Real_Target)();
|
||||
}
|
||||
|
||||
void (CDetour::* CDetour::Real_Target)(void) = (void (CDetour::*)(void))&CMember::Target;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
void (CMember::* pfTarget)(void) = &CMember::Target;
|
||||
void (CDetour::* pfMine)(void) = &CDetour::Mine_Target;
|
||||
|
||||
Verify("CMember::Target ", *(PBYTE*)&pfTarget);
|
||||
Verify("*CDetour::Real_Target", *(PBYTE*)&CDetour::Real_Target);
|
||||
Verify("CDetour::Mine_Target ", *(PBYTE*)&pfMine);
|
||||
|
||||
printf("\n");
|
||||
|
||||
DetourTransactionBegin();
|
||||
DetourUpdateThread(GetCurrentThread());
|
||||
|
||||
DetourAttach(&(PVOID&)CDetour::Real_Target,
|
||||
*(PBYTE*)&pfMine);
|
||||
|
||||
LONG l = DetourTransactionCommit();
|
||||
printf("DetourTransactionCommit = %ld\n", l);
|
||||
printf("\n");
|
||||
|
||||
Verify("CMember::Target ", *(PBYTE*)&pfTarget);
|
||||
Verify("*CDetour::Real_Target", *(&(PBYTE&)CDetour::Real_Target));
|
||||
Verify("CDetour::Mine_Target ", *(PBYTE*)&pfMine);
|
||||
printf("\n");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
CMember target;
|
||||
|
||||
printf("Calling CMember (w/o Detour):\n");
|
||||
(((CDetour*)&target)->*CDetour::Real_Target)();
|
||||
|
||||
printf("Calling CMember (will be detoured):\n");
|
||||
target.Target();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user