Figure 1: CallMonitor hook implementation

// Copyright (c) 1998 John Panzer.  Permission is granted to
// use, copy, modify, distribute, and sell this source code as 
// long as this copyright notice appears in all source files.
#include <windows.h>
#include <imagehlp.h>
#include <stdio.h>
#include "CallMon.h"

using namespace std;

typedef CallMonitor::ADDR ADDR;

// Processor-specific offset from
// _penter return address to start of
// caller.
static const unsigned OFFSET_CALL_BYTES=5;

// Start of MSVC-specific code

// _pexit is called upon return from
// an instrumented function.
static void _pexit()
    CallMonitor::TICKS endTime;
    ADDR framePtr,parentFramePtr;

    // Retrieve parent stack frame to pass
    // to exitProcedure
    __asm mov DWORD PTR [framePtr], ebp
    parentFramePtr = ((ADDR *)framePtr)[0];


// An entry point to which all instrumented
// function returns are redirected.  
static void __declspec(naked) _pexitThunk()
    // Push placeholder return address
    __asm push 0     
    // Protect original return value
    __asm push eax   
    // Restore original return value
    __asm pop eax    
    // Return using new address set by _pexit
    __asm ret        

// _penter is called on entry to each client function
extern "C" __declspec(dllexport)
void _penter()
    CallMonitor::TICKS entryTime;
    CallMonitor::queryTicks(&entryTime); // Track entry time

    ADDR framePtr;
    __asm mov DWORD PTR [framePtr], ebp

        (ADDR)((unsigned *)framePtr)[0],
        (ADDR)((unsigned *)framePtr)[1]-OFFSET_CALL_BYTES,
        (ADDR*)&((unsigned *)framePtr)[2],
// End of MSVC-specific code

//End of File