home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_04 / Diver / Proxy.cpp < prev    next >
C/C++ Source or Header  |  2000-05-11  |  6KB  |  199 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : proxy.cpp                                                             //
  10. //  Description: API hacking gluing routines                                         //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define NOCRYPT
  15.  
  16. #include <windows.h>
  17. #include <assert.h>
  18.  
  19. #include "..\..\include\Decoder.h"
  20. #include "..\..\include\atom.h"
  21.  
  22. #include "Function.h"
  23. #include "Stack.h"
  24.  
  25. // para n
  26. // para n-1
  27. // ...
  28. // para 1
  29. // return address
  30. // func_id
  31. // ecx = this
  32.  
  33. unsigned           OverHead = 0;
  34. long               Lock     = 0;
  35.  
  36. void ProxyInit(void)
  37. {
  38.     __asm   _emit   0x0F                // read Pentium clock cycle into EDX:EAX
  39.     __asm   _emit   0x31
  40.     __asm   shrd    eax, edx, 8         // EAX = EDX:EAX >> 8
  41.     __asm   mov     OverHead, eax
  42.  
  43.     Lock = 0;
  44. }
  45.  
  46.  
  47. void _stdcall ProxyExit(ExitInfo *info, unsigned leavetime)
  48. {
  49.     int depth;
  50.  
  51.     assert(pStack);
  52.  
  53.     KRoutineInfo * routine = pStack->Lookup(depth);
  54.  
  55.     if ( routine )
  56.     {
  57.         pFuncTable->FuncExitCallBack(routine, info, leavetime, depth);
  58.         info->m_rslt = routine->rtnaddr;
  59.  
  60.         pStack->Pop();
  61.     }
  62. }
  63.  
  64.  
  65. _declspec(naked) void ProxyEpilog(void)
  66. {
  67.     // placehold for return address
  68.     __asm    push    eax                    // placehold for return address
  69.  
  70.     // save common registers
  71.     __asm   push    eax
  72.     __asm   push    ebx
  73.     __asm   push    ecx
  74.     __asm   push    edx                 // 4*4=16
  75.     __asm   pushfd                        // 4
  76.     
  77.     // read cpu clock cycles
  78.     __asm   _emit   0x0F                // read Pentium clock cycle into EDX:EAX
  79.     __asm   _emit   0x31                // time3
  80.     __asm   shrd    eax, edx, 8         // EAX = EDX:EAX >> 8
  81.  
  82.     // push leaving clock, leaving time on stack
  83.     __asm   push    eax                 // leaving clock
  84.     __asm   sub     eax, OverHead       
  85.     __asm   push    eax                 // leaving clock - overhead
  86.  
  87.   //  while (Lock);                       // wait for lock
  88.   //  InterlockedIncrement(& Lock);
  89.  
  90.     // pushing pointer to return address placehold, call ProxyExit
  91.     __asm    lea        eax, [esp+28]        // offset for eax(placehold) on stack
  92.     __asm    push    eax
  93.     __asm    call    ProxyExit
  94.  
  95.     // read cpu clock cycle, update Overhead
  96.     __asm   pop     ecx                 // ecx = entering clock
  97.     __asm   _emit   0x0F                // time4
  98.     __asm   _emit   0x31
  99.     __asm   shrd    eax, edx, 8         // EAX = EDX:EAX >> 8
  100.     __asm   sub     eax, ecx            // new overhead by ProxyEpilog
  101.     __asm   add     OverHead, eax
  102.     
  103.  // InterlockedDecrement(& Lock);
  104.  
  105.     // restore common registers
  106.     __asm   popfd
  107.     __asm   pop     edx
  108.     __asm   pop     ecx
  109.     __asm   pop     ebx
  110.     __asm   pop     eax
  111.  
  112.     // return to address stored in placehold, the original caller
  113.     __asm    ret
  114. }
  115.  
  116. void _stdcall ProxyEntry(EntryInfo *info, unsigned entertime)
  117. {
  118.     int id = info->m_funcid;
  119.     
  120.     assert(pStack!=NULL);
  121.     KRoutineInfo * routine = pStack->Push();
  122.  
  123.     if ( routine )
  124.     {
  125.         routine->entertime = entertime;
  126.         routine->funcid    = id;
  127.         routine->rtnaddr   = info->m_rtnads;
  128.  
  129.         pFuncTable->FuncEntryCallBack(routine, info);
  130.     
  131.         // if pushing is succeful, patch return address such that original 
  132.         // function will go to our epilog code before returning to caller
  133.         info->m_rtnads = (unsigned) ProxyEpilog;
  134.     }            
  135.     
  136.     // make sure controls goes to original function when ProxyProlog returns
  137.     info->m_funcid = (unsigned) pFuncTable->m_func[id].f_oldaddress;
  138. }
  139.  
  140.  
  141.  
  142. //   ProxyProlog        inline assembly naked
  143. //       ProxyEntry     C++             stdcall
  144. //   Original Callee
  145. //   ProxyEpilog        inline assembly naked
  146. //       ProxyExit      C++             stdcall
  147. //   Original caller    
  148. _declspec(naked) void ProxyProlog(void)
  149. {
  150.                                         // funcid already pushed on stack by stub code 
  151.                                         // generated by KFunction::InitStub
  152.     // funcid already on stack, place hold for original callee address
  153.  
  154.     // save common registers
  155.     __asm   push    eax
  156.     __asm   push    ebx
  157.     __asm    push    ecx                    
  158.     __asm   push    edx                 // edx, ecx, ebx, eax, funcid, rtnadr, p1..pn
  159.     __asm   pushfd                        // 4      bytes EFLAGS
  160.     
  161.     // read cpu clock cycle count
  162.     __asm   _emit   0x0F                // read Pentium clock cycle into EDX:EAX
  163.     __asm   _emit   0x31                // time1
  164.     __asm   shrd    eax, edx, 8         // EAX = EDX:EAX >> 8
  165.  
  166.     // pushing entering clock, entering time
  167.     __asm   push    eax                 // entering clock
  168.     __asm   sub     eax, OverHead       
  169.     __asm   push    eax                 // entering clock - overhead
  170.  
  171.  // while (Lock);
  172.  // InterlockedIncrement(& Lock);
  173.  
  174.     // push offset to common registers, call ProxyEntry
  175.     __asm    lea        eax, [esp+8]        // offset for flag on stack        
  176.     __asm    push    eax
  177.     __asm    call    ProxyEntry
  178.     
  179.     // read cpu clock cycle count, update overhead
  180.     __asm   pop     ecx                 // ecx = entering clock
  181.     __asm   _emit   0x0F                // time2
  182.     __asm   _emit   0x31
  183.     __asm   shrd    eax, edx, 8         // EAX = EDX:EAX >> 8
  184.     __asm   sub     eax, ecx            // new overhead by ProxyEntry
  185.     __asm   add     OverHead, eax
  186.  
  187.  // InterlockedDecrement(& Lock);
  188.  
  189.     // restore common registers
  190.     __asm    popfd
  191.     __asm   pop     edx
  192.     __asm    pop        ecx                    
  193.     __asm   pop     ebx
  194.     __asm   pop     eax
  195.  
  196.     // switch control to original callee
  197.     __asm    ret                         // control continues to original callee
  198. }
  199.