home *** CD-ROM | disk | FTP | other *** search
/ C Programming Starter Kit 2.0 / SamsPublishing-CProgrammingStarterKit-v2.0-Win31.iso / bc45 / owlsrc.pak / OWL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-07-24  |  5.7 KB  |  224 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // (C) Copyright 1991, 1994 by Borland International, All Rights Reserved
  4. //
  5. //   Internal object thunk creation & maintanance.
  6. //----------------------------------------------------------------------------
  7. #include <owl/owlpch.h>
  8. #include <owl/window.h>
  9. #include <dos.h>
  10. #include <mem.h>
  11. #if defined(BI_PLAT_WIN32)
  12. # include <stddef.h>
  13. #endif
  14.  
  15. LRESULT FAR PASCAL _export StdWndProc(HWND, uint, WPARAM, LPARAM);
  16. TProcInstance StdWndProcInstance((FARPROC)StdWndProc);
  17.  
  18. //
  19. // Creation window pointer for InitWndProc
  20. //
  21. TWindow* _OWLDATA CreationWindow = 0;
  22.  
  23. void _OWLFUNC
  24. SetCreationWindow(TWindow* w)
  25. {
  26.   CreationWindow = w;
  27. }
  28.  
  29. uint16 far _OWLFUNC
  30. OWLGetVersion()
  31. {
  32.   return OWLVersion;
  33. }
  34.  
  35. //
  36. // Initial WndProc called when an Owl window is first created.
  37. // Subclasses the window function by installing the thunk then calls the
  38. // thunk to get this first message to the window.
  39. //
  40. LRESULT CALLBACK __export
  41. InitWndProc(HWND hWindow, uint message, WPARAM wParam, LPARAM lParam)
  42. {
  43.   // If there's no creation window, i.e. we'll be aliasing a resource,
  44.   // then we can't do anything now.  Create() will take care of it later
  45.   //
  46.   if (!CreationWindow)
  47.     return ::DefWindowProc(hWindow, message, wParam, lParam);
  48.  
  49.   // install "DefWindowProc" as the window function BEFORE we request the
  50.   // subclassings; otherwise it looks like we subclassed "InitWndProc"
  51.   //
  52.   CreationWindow->HWindow = hWindow;
  53. #if defined(BI_PLAT_WIN32)
  54.   CreationWindow->DefaultProc = (WNDPROC)GetProcAddress(
  55.       (HINSTANCE)GetModuleHandle("USER32"), "DefWindowProcA");
  56. #else
  57.   CreationWindow->DefaultProc = ::DefWindowProc;
  58. #endif
  59.  
  60.   // Get the thunk & then zero out creation window so that it is not 
  61.   // inadvertently used.
  62.   //
  63.   WNDPROC thunk = CreationWindow->GetThunk();
  64.   CreationWindow = 0;
  65.  
  66.   // Set the thunk as the window proc, & call it with this first message.
  67.   //
  68.   SetWindowLong(hWindow, GWL_WNDPROC, uint32(thunk));
  69.   return (*(WNDPROC)(thunk))(hWindow, message, wParam, lParam);
  70. }
  71.  
  72. //
  73. // Win32 version of the instance thunking mechanism
  74. //
  75. #if defined(BI_PLAT_WIN32)
  76.  
  77. struct TInstanceThunk {
  78.   char     Call;
  79.   int      Offset;
  80.   PROC     WndProcPtr;
  81.   TWindow* Window;
  82.   char     Code[6];
  83. };
  84.  
  85. static const int  CODEDISP = offsetof(TInstanceThunk, Code) -
  86.                              offsetof(TInstanceThunk, WndProcPtr);
  87.  
  88. WNDPROC
  89. CreateInstanceThunk(TWindow* w)
  90. {
  91.   TInstanceThunk*  thunk = new TInstanceThunk;
  92.  
  93.   thunk->Call = 0xE8;         // CALL rel32
  94.   thunk->Offset = CODEDISP;   // relative displacement to Code[5]
  95.   thunk->WndProcPtr = StdWndProcInstance;
  96.   thunk->Window = w;
  97.  
  98.   //
  99.   // POP ECX
  100.   //
  101.   // pop return address of call into ecx (address of member "WndProcPtr")
  102.   //
  103.   thunk->Code[0] = 0x59;
  104.  
  105.   //
  106.   // MOV EAX,[ECX+4]
  107.   //
  108.   // load "Window" into ebx
  109.   //
  110.   thunk->Code[1] = 0x8B;     // MOV r32,r/m32
  111.   thunk->Code[2] = 0x41;     // eax,disp8[ECX]
  112.   thunk->Code[3] = 0x04;     // +4
  113.  
  114.   //
  115.   // JMP [ECX]
  116.   //
  117.   // jump to window function StdWndProc
  118.   //
  119.   thunk->Code[4] = 0xFF;     // JMP r/m32
  120.   thunk->Code[5] = 0x21;     // [ECX]
  121.  
  122.   return (WNDPROC)thunk;
  123. }
  124.  
  125. void
  126. FreeInstanceThunk(WNDPROC proc)
  127. {
  128.   delete (TInstanceThunk*)proc;
  129. }
  130.  
  131. //
  132. // Win16 version of the instance thunking mechanism
  133. //
  134. #elif defined(BI_PLAT_WIN16)
  135.  
  136. //
  137. // AllocCSToDSAlias was not declared in windows.h
  138. //
  139. extern "C" uint16 FAR PASCAL AllocCSToDSAlias(uint16);
  140.  
  141. struct TInstanceThunk {
  142.   char   Code;
  143.   uint16 Offset;
  144.  
  145.   union Ptr {
  146.     struct TInstanceThunk far* Next;
  147.     TWindow far*               Window;
  148.   } ptr;
  149. };
  150.  
  151. struct TThunkBlock {
  152.   uint16    Next;
  153.   char      Code[5];
  154.   void far* WndProcPtr;
  155.   struct TInstanceThunk Thunks[34];
  156. };
  157.  
  158. static uint16              ThunkBlockList = 0;
  159. static TInstanceThunk far* ThunkFreeList = 0;
  160.  
  161. WNDPROC
  162. CreateInstanceThunk(TWindow* w)
  163. {
  164.   char                blockCode[5];
  165.   TThunkBlock far*    block;
  166.   TInstanceThunk far* thunk;
  167.   WNDPROC             objInstance;
  168.  
  169.   // POP BX
  170.   blockCode[0] = 0x5b;
  171.  
  172.   // LES BX, CS:[BX]
  173.   blockCode[1] = 0x2e;
  174.   blockCode[2] = 0xc4;
  175.   blockCode[3] = 0x1f;
  176.  
  177.   // JMP FAR StdWndProc
  178.   blockCode[4] = 0xea;
  179.  
  180.   if (!ThunkFreeList) {
  181.     block = (TThunkBlock far*)GlobalLock(GlobalAlloc(GMEM_FIXED | GMEM_SHARE | GMEM_NOT_BANKED,
  182.                                          sizeof(TThunkBlock)));
  183.     block->Next = ThunkBlockList;
  184.     memcpy(block->Code, blockCode, 5);
  185.     block->WndProcPtr = (void far*)StdWndProcInstance;
  186.     thunk = block->Thunks;
  187.  
  188.     do {
  189.       thunk->Code = 0xE8;
  190.       thunk->Offset = (2 - 3) - FP_OFF(thunk);
  191.       thunk->ptr.Next = ThunkFreeList;
  192.       ThunkFreeList = thunk;
  193.       thunk = (TInstanceThunk far*)MK_FP(
  194.                     FP_SEG(thunk),
  195.                     FP_OFF(thunk)+sizeof(TInstanceThunk)
  196.                  );
  197.     } while (FP_OFF(thunk) != sizeof(TThunkBlock));
  198.  
  199.     ThunkBlockList = FP_SEG(block);
  200.     PrestoChangoSelector(FP_SEG(block), FP_SEG(block));
  201.   }
  202.  
  203.   objInstance = (WNDPROC)ThunkFreeList;
  204.   thunk = (TInstanceThunk far*)MK_FP(AllocCSToDSAlias(FP_SEG(ThunkFreeList)),
  205.                                                       FP_OFF(ThunkFreeList));
  206.   ThunkFreeList = thunk->ptr.Next;
  207.   thunk->ptr.Window = (TWindow far*)w;
  208.   FreeSelector(FP_SEG(thunk));
  209.   return objInstance;
  210. }
  211.  
  212. void
  213. FreeInstanceThunk(WNDPROC p)
  214. {
  215.   TInstanceThunk far* thunk = (TInstanceThunk far*)MK_FP(AllocCSToDSAlias(FP_SEG(p)),
  216.                                                        FP_OFF(p));
  217.  
  218.   thunk->ptr.Next = ThunkFreeList;
  219.   FreeSelector(FP_SEG(thunk));
  220.   ThunkFreeList = (TInstanceThunk far*)p;
  221. }
  222.  
  223. #endif  // BI_PLAT_XXX
  224.