home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c083 / 11.ddi / OWLSRC.PAK / OWL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-02  |  6.7 KB  |  266 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows - (C) Copyright 1991, 1993 by Borland International
  3. //   source\owl\owl.cpp
  4. //----------------------------------------------------------------------------
  5. #include <owl\owlpch.h>
  6. #include <owl\window.h>
  7. #include <dos.h>
  8. #include <mem.h>
  9.  
  10. #if defined(__WIN32__)
  11.   #include <stddef.h>
  12. #endif
  13.  
  14. LRESULT FAR PASCAL _export StdWndProc(HWND, UINT, WPARAM, LPARAM);
  15. TProcInstance StdWndProcInstance((FARPROC)StdWndProc);
  16.  
  17. //
  18. // creation window pointers for InitWndProc
  19. //
  20. TWindow* _OWLDATA CreationWindow = 0;
  21.  
  22. void _OWLFUNC
  23. SetCreationWindow(TWindow* w)
  24. {
  25.   CreationWindow = w;
  26. }
  27.  
  28. unsigned short far _OWLFUNC
  29. OWLGetVersion()
  30. {
  31.   return OWLVersion;
  32. }
  33.  
  34. //
  35. // subclasses the window function and installs the thunk
  36. //
  37. LRESULT
  38. FAR PASCAL _export
  39. InitWndProc(HWND hWindow, UINT message, WPARAM wParam, LPARAM lParam)
  40. {
  41.   // If there's no creation window, ie we'll be aliasing a resource
  42.   // then we can't do anything now.  Create() will take care of it later
  43.   //
  44.   if (!CreationWindow)
  45.     return ::DefWindowProc(hWindow, message, wParam, lParam);
  46.  
  47.   //
  48.   // install "DefWindowProc" as the window function BEFORE we request the
  49.   // subclassings; otherwise it looks like we subclassed "InitWndProc"
  50.   //
  51.   CreationWindow->HWindow = hWindow;
  52.   #if defined(__WIN32__)
  53.     CreationWindow->DefaultProc = (WNDPROC)GetProcAddress(
  54.       (HINSTANCE)GetModuleHandle("USER32"), "DefWindowProcA");
  55.   #else
  56.     CreationWindow->DefaultProc = ::DefWindowProc;
  57.   #endif
  58.  
  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.   //
  67.   // Set the thunk as the window proc, & call it with this first message.
  68.   //
  69.   SetWindowLong(hWindow, GWL_WNDPROC, DWORD(thunk));
  70.   return (*(WNDPROC)(thunk))(hWindow, message, wParam, lParam);
  71. }
  72.  
  73. #if defined(__WIN32__)
  74. struct TInstanceThunk {
  75.   char     Call;
  76.   int      Offset;
  77.   PROC     WndProcPtr;
  78.   TWindow* Window;
  79.   char     Code[6];
  80. };
  81.  
  82. static const int  CODEDISP = offsetof(TInstanceThunk, Code) -
  83.                              offsetof(TInstanceThunk, WndProcPtr);
  84.  
  85. //
  86. // return pointer to TWindow given a window handle
  87. //
  88. UINT _OWLDATA GetWindowPtrMsgId = 0;
  89.  
  90. TWindow* _OWLFUNC
  91. GetWindowPtr(HWND hWnd)
  92. {
  93.   //
  94.   // determine the object pointer by sending a "GetWindowPtr()" message
  95.   // to the window.  When the first StdWndProc() in the subclass chain
  96.   // receives this message it returns a pointer to the object (via the
  97.   // thunking mechanism).
  98.   //
  99.   if (!hWnd)
  100.     return 0;
  101. //  return (TWindow*)::SendMessage(hWnd, GetWindowPtrMsgId, 0, 0);
  102.  
  103.   WNDPROC wndProc = (WNDPROC)::GetWindowLong(hWnd, GWL_WNDPROC);
  104.   if (!wndProc)
  105.     return 0;
  106.   return (TWindow*)::CallWindowProc(wndProc, hWnd, GetWindowPtrMsgId, 0, 0);
  107. }
  108.  
  109. WNDPROC
  110. CreateInstanceThunk(TWindow* w)
  111. {
  112.   TInstanceThunk*  thunk = new TInstanceThunk;
  113.  
  114.   thunk->Call = 0xE8;         // CALL rel32
  115.   thunk->Offset = CODEDISP;   // relative displacement to Code[5]
  116.   thunk->WndProcPtr = StdWndProcInstance;
  117.   thunk->Window = w;
  118.  
  119.   //
  120.   // POP ECX
  121.   //
  122.   // pop return address of call into ecx (address of member "WndProcPtr")
  123.   //
  124.   thunk->Code[0] = 0x59;
  125.  
  126.   //
  127.   // MOV EAX,[ECX+4]
  128.   //
  129.   // load "Window" into ebx
  130.   //
  131.   thunk->Code[1] = 0x8B;     // MOV r32,r/m32
  132.   thunk->Code[2] = 0x41;     // eax,disp8[ECX]
  133.   thunk->Code[3] = 0x04;     // +4
  134.  
  135.   //
  136.   // JMP [ECX]
  137.   //
  138.   // jump to window function StdWndProc
  139.   //
  140.   thunk->Code[4] = 0xFF;     // JMP r/m32
  141.   thunk->Code[5] = 0x21;     // [ECX]
  142.  
  143.   return (WNDPROC)thunk;
  144. }
  145.  
  146. void
  147. FreeInstanceThunk(WNDPROC proc)
  148. {
  149.   delete (TInstanceThunk*)proc;
  150. }
  151.  
  152. #else  // Win16
  153.  
  154. //
  155. // AllocCSToDSAlias was not declared in windows.h
  156. //
  157. extern "C" WORD FAR PASCAL AllocCSToDSAlias(WORD);
  158.  
  159. struct TInstanceThunk {
  160.   char   Code;
  161.   WORD   Offset;
  162.  
  163.   union Ptr {
  164.     struct TInstanceThunk far* Next;
  165.     TWindow far*               Window;
  166.   } ptr;
  167. };
  168.  
  169. struct TThunkBlock {
  170.   WORD      Next;
  171.   char      Code[5];
  172.   void far* WndProcPtr;
  173.   struct TInstanceThunk Thunks[34];
  174. };
  175.  
  176. static WORD                ThunkBlockList = 0;
  177. static TInstanceThunk far* ThunkFreeList = 0;
  178.  
  179. //
  180. // return pointer to TWindow given a window handle
  181. //
  182. UINT _OWLDATA GetWindowPtrMsgId = 0;
  183.  
  184. //
  185. // determine the object pointer by sending a "GetWindowPtr()" message
  186. // to the window.  When the first StdWndProc() in the subclass chain
  187. // receives this message it returns a pointer to the object (via the
  188. // thunking mechanism).
  189. //
  190. TWindow* _OWLFUNC
  191. GetWindowPtr(HWND hWnd)
  192. {
  193.   if (!hWnd)
  194.     return 0;
  195. //  return (TWindow*)::SendMessage(hWnd, GetWindowPtrMsgId, 0, 0);
  196.  
  197.   WNDPROC wndProc = (WNDPROC)::GetWindowLong(hWnd, GWL_WNDPROC);
  198.   if (!wndProc)
  199.     return 0;
  200.   return (TWindow*)::CallWindowProc(wndProc, hWnd, GetWindowPtrMsgId, 0, 0);
  201. }
  202.  
  203. WNDPROC
  204. CreateInstanceThunk(TWindow* w)
  205. {
  206.   char                blockCode[5];
  207.   TThunkBlock far*    block;
  208.   TInstanceThunk far* thunk;
  209.   WNDPROC             objInstance;
  210.  
  211.   // POP BX
  212.   blockCode[0] = 0x5b;
  213.  
  214.   // LES BX, CS:[BX]
  215.   blockCode[1] = 0x2e;
  216.   blockCode[2] = 0xc4;
  217.   blockCode[3] = 0x1f;
  218.  
  219.   // JMP FAR StdWndProc
  220.   blockCode[4] = 0xea;
  221.  
  222.   if (!ThunkFreeList) {
  223.     block = (TThunkBlock far*)GlobalLock(GlobalAlloc(GMEM_FIXED | GMEM_DDESHARE | GMEM_NOT_BANKED,
  224.                                          sizeof(TThunkBlock)));
  225.     block->Next = ThunkBlockList;
  226.     memcpy(block->Code, blockCode, 5);
  227.     block->WndProcPtr = (void far*)StdWndProcInstance;
  228.     thunk = block->Thunks;
  229.  
  230.     do {
  231.       thunk->Code = 0xE8;
  232.       thunk->Offset = (2 - 3) - FP_OFF(thunk);
  233.       thunk->ptr.Next = ThunkFreeList;
  234.       ThunkFreeList = thunk;
  235.       thunk = (TInstanceThunk far*)MK_FP(
  236.                     FP_SEG(thunk),
  237.                     FP_OFF(thunk)+sizeof(TInstanceThunk)
  238.                  );
  239.     } while (FP_OFF(thunk) != sizeof(TThunkBlock));
  240.  
  241.     ThunkBlockList = FP_SEG(block);
  242.     PrestoChangoSelector(FP_SEG(block), FP_SEG(block));
  243.   }
  244.  
  245.   objInstance = (WNDPROC)ThunkFreeList;
  246.   thunk = (TInstanceThunk far*)MK_FP(AllocCSToDSAlias(FP_SEG(ThunkFreeList)),
  247.                                                       FP_OFF(ThunkFreeList));
  248.   ThunkFreeList = thunk->ptr.Next;
  249.   thunk->ptr.Window = (TWindow far*)w;
  250.   FreeSelector(FP_SEG(thunk));
  251.   return objInstance;
  252. }
  253.  
  254. void
  255. FreeInstanceThunk(WNDPROC p)
  256. {
  257.   TInstanceThunk far* thunk = (TInstanceThunk far*)MK_FP(AllocCSToDSAlias(FP_SEG(p)),
  258.                                                        FP_OFF(p));
  259.  
  260.   thunk->ptr.Next = ThunkFreeList;
  261.   FreeSelector(FP_SEG(thunk));
  262.   ThunkFreeList = (TInstanceThunk far*)p;
  263. }
  264.  
  265. #endif //__WIN32__
  266.