168 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			168 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | //  Detour Test Program (wrotei.cpp of wrotei.dll)
 | ||
|  | //
 | ||
|  | //  Microsoft Research Detours Package
 | ||
|  | //
 | ||
|  | //  Copyright (c) Microsoft Corporation.  All rights reserved.
 | ||
|  | //
 | ||
|  | //  An example dynamically detouring a function.
 | ||
|  | //
 | ||
|  | #include <stdio.h>
 | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | //  WARNING:
 | ||
|  | //
 | ||
|  | //  CINTERFACE must be defined so that the lpVtbl pointer is visible
 | ||
|  | //  on COM interfaces.  However, once we've defined it, we must use
 | ||
|  | //  coding conventions when accessing interface members, for example:
 | ||
|  | //      i->lpVtbl->Write
 | ||
|  | //  instead of the C++ syntax:
 | ||
|  | //      i->Write.
 | ||
|  | //  We must also pass the implicit "this" parameter explicitly:
 | ||
|  | //      i->lpVtbl->Write(i, pb, 0, NULL)
 | ||
|  | //  instead of the C++ syntax:
 | ||
|  | //      i->Write(pb, 0, NULL)
 | ||
|  | //
 | ||
|  | #define CINTERFACE
 | ||
|  | #include <ole2.h>
 | ||
|  | #include <windows.h>
 | ||
|  | #include <detours.h>
 | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | LONG dwWrote = 0; | ||
|  | 
 | ||
|  | static int (WINAPI * TrueEntryPoint)(VOID) = NULL; | ||
|  | static int (WINAPI * RawEntryPoint)(VOID) = NULL; | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | HRESULT (STDMETHODCALLTYPE *RealIStreamWrite)(IStream * This, | ||
|  |                                               const void *pv, | ||
|  |                                               ULONG cb, | ||
|  |                                               ULONG *pcbWritten) = NULL; | ||
|  | 
 | ||
|  | HRESULT STDMETHODCALLTYPE MineIStreamWrite(IStream * This, | ||
|  |                                            const void *pv, | ||
|  |                                            ULONG cb, | ||
|  |                                            ULONG *pcbWritten) | ||
|  | { | ||
|  |     HRESULT hr; | ||
|  |     ULONG cbWritten = 0; | ||
|  |     if (pcbWritten == NULL) { | ||
|  |         pcbWritten = &cbWritten; | ||
|  |     } | ||
|  | 
 | ||
|  |     hr = RealIStreamWrite(This, pv, cb, pcbWritten); | ||
|  | 
 | ||
|  |     for (;;) { | ||
|  |         LONG dwOld = dwWrote; | ||
|  |         LONG dwNew = dwOld + *pcbWritten; | ||
|  | 
 | ||
|  |         if (InterlockedCompareExchange(&dwWrote, dwNew, dwOld) == dwOld) { | ||
|  |             break; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     return hr; | ||
|  | } | ||
|  | 
 | ||
|  | //////////////////////////////////////////////////////////////////////////////
 | ||
|  | //
 | ||
|  | int WINAPI TimedEntryPoint(VOID) | ||
|  | { | ||
|  |     // We couldn't call CoInitializeEx in DllMain,
 | ||
|  |     // so we detour the vtable entries here...
 | ||
|  |     LONG error; | ||
|  |     LPSTREAM pStream = NULL; | ||
|  | 
 | ||
|  |     // Create a temporary object so we can get a vtable.
 | ||
|  |     CreateStreamOnHGlobal(NULL, TRUE, &pStream); | ||
|  | 
 | ||
|  |     // Apply the detour to the vtable.
 | ||
|  |     DetourTransactionBegin(); | ||
|  |     DetourUpdateThread(GetCurrentThread()); | ||
|  |     if (pStream != NULL) { | ||
|  |         RealIStreamWrite = pStream->lpVtbl->Write; | ||
|  |         DetourAttach(&(PVOID&)RealIStreamWrite, MineIStreamWrite); | ||
|  |     } | ||
|  |     error = DetourTransactionCommit(); | ||
|  | 
 | ||
|  |     if (pStream != NULL) { | ||
|  |         pStream->lpVtbl->Release(pStream); | ||
|  |         pStream = NULL; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (error == NO_ERROR) { | ||
|  |         printf("wrotei" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:" | ||
|  |                " Detoured IStream::Wrote() from OnHGlobal.\n"); | ||
|  |     } | ||
|  |     else { | ||
|  |         printf("wrotei" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:" | ||
|  |                " Error detouring IStram::Wrote(): %ld\n", error); | ||
|  |     } | ||
|  | 
 | ||
|  |     printf("wrotei" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:" | ||
|  |            " Calling EntryPoint\n\n"); | ||
|  |     fflush(stdout); | ||
|  | 
 | ||
|  |     return TrueEntryPoint(); | ||
|  | } | ||
|  | 
 | ||
|  | BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) | ||
|  | { | ||
|  |     LONG error; | ||
|  |     (void)hinst; | ||
|  |     (void)reserved; | ||
|  | 
 | ||
|  |     if (DetourIsHelperProcess()) { | ||
|  |         return TRUE; | ||
|  |     } | ||
|  | 
 | ||
|  |     if (dwReason == DLL_PROCESS_ATTACH) { | ||
|  |         DetourRestoreAfterWith(); | ||
|  | 
 | ||
|  |         printf("wrotei" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:" | ||
|  |                " Starting.\n"); | ||
|  |         fflush(stdout); | ||
|  | 
 | ||
|  |         // NB: DllMain can't call LoadLibrary, so we hook the app entry point.
 | ||
|  |         TrueEntryPoint = (int (WINAPI *)(VOID))DetourGetEntryPoint(NULL); | ||
|  |         RawEntryPoint = TrueEntryPoint; | ||
|  | 
 | ||
|  |         DetourTransactionBegin(); | ||
|  |         DetourUpdateThread(GetCurrentThread()); | ||
|  |         DetourAttach(&(PVOID&)TrueEntryPoint, TimedEntryPoint); | ||
|  |         error = DetourTransactionCommit(); | ||
|  | 
 | ||
|  |         if (error == NO_ERROR) { | ||
|  |             printf("wrotei" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:" | ||
|  |                    " Detoured EntryPoint().\n"); | ||
|  |         } | ||
|  |         else { | ||
|  |             printf("wrotei" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:" | ||
|  |                    " Error detouring EntryPoint(): %ld\n", error); | ||
|  |         } | ||
|  |     } | ||
|  |     else if (dwReason == DLL_PROCESS_DETACH) { | ||
|  |         DetourTransactionBegin(); | ||
|  |         DetourUpdateThread(GetCurrentThread()); | ||
|  |         if (RealIStreamWrite != NULL) { | ||
|  |             DetourDetach(&(PVOID&)RealIStreamWrite, (PVOID)MineIStreamWrite); | ||
|  |         } | ||
|  |         DetourDetach(&(PVOID&)TrueEntryPoint, TimedEntryPoint); | ||
|  |         error = DetourTransactionCommit(); | ||
|  | 
 | ||
|  |         printf("wrotei" DETOURS_STRINGIFY(DETOURS_BITS) ".dll:" | ||
|  |                " Removed IStream::Wrote() detours (%ld), wrote %ld bytes.\n", | ||
|  |                error, dwWrote); | ||
|  | 
 | ||
|  |         fflush(stdout); | ||
|  |     } | ||
|  |     return TRUE; | ||
|  | } | ||
|  | //
 | ||
|  | ///////////////////////////////////////////////////////////////// End of File.
 |