classes.pp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. {
  2. This file is part of the Free Component Library (FCL)
  3. Copyright (c) 1998 by Michael Van Canneyt and Florian Klaempfl
  4. Classes unit for win32
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. {$H+}
  13. {$IF FPC_FULLVERSION>=30301}
  14. {$modeswitch FUNCTIONREFERENCES}
  15. {$define FPC_HAS_REFERENCE_PROCEDURE}
  16. {$endif}
  17. { determine the type of the resource/form file }
  18. {$define Win16Res}
  19. unit Classes;
  20. interface
  21. uses
  22. rtlconsts,
  23. sysutils,
  24. types,
  25. sortbase,
  26. {$ifdef FPC_TESTGENERICS}
  27. fgl,
  28. {$endif}
  29. typinfo,
  30. windows;
  31. type
  32. TWndMethod = procedure(var msg : TMessage) of object;
  33. function MakeObjectInstance(Method: TWndMethod): Pointer;
  34. procedure FreeObjectInstance(ObjectInstance: Pointer);
  35. function AllocateHWnd(Method: TWndMethod): HWND;
  36. procedure DeallocateHWnd(Wnd: HWND);
  37. {$i classesh.inc}
  38. implementation
  39. uses
  40. sysconst;
  41. { OS - independent class implementations are in /inc directory. }
  42. {$i classes.inc}
  43. type
  44. PMethodWrapperTrampoline = ^TMethodWrapperTrampoline;
  45. PWrapperBlock = ^TWrapperBlock;
  46. TMethodWrapperTrampoline = packed record
  47. Call : byte;
  48. CallOffset : PtrInt;
  49. Jmp : byte;
  50. JmpOffset : PtrInt;
  51. case Integer of
  52. 0: (Next: PMethodWrapperTrampoline; Block : PWrapperBlock);
  53. 1: (Method: TWndMethod);
  54. end;
  55. TWrapperBlock = packed record
  56. Next : PWrapperBlock;
  57. UsageCount : Longint;
  58. Trampolines : array[0..0] of TMethodWrapperTrampoline;
  59. end;
  60. var
  61. WrapperBlockList : PWrapperBlock;
  62. TrampolineFreeList : PMethodWrapperTrampoline;
  63. CritObjectInstance : TCriticalSection;
  64. function TrampolineWndProc(Window: HWND; Message, WParam: WPARAM;LParam: LPARAM): HRESULT; stdcall; assembler;
  65. asm
  66. // build up tmessage structure
  67. pushl $0
  68. movl (%eax),%ecx
  69. pushl LPARAM
  70. pushl WPARAM
  71. pushl Message
  72. // msg
  73. leal (%esp),%edx
  74. // load self
  75. movl 4(%eax),%eax
  76. // call method
  77. call %ecx
  78. addl $12,%esp
  79. // load result
  80. popl %eax
  81. end;
  82. function get_method_offset : Pointer;assembler;nostackframe;
  83. asm
  84. movl (%esp),%eax
  85. addl $5,%eax
  86. end;
  87. const
  88. SizeOfPage = 4096;
  89. function MakeObjectInstance(Method: TWndMethod): Pointer;
  90. var
  91. NewBlock : PWrapperBlock;
  92. Trampoline : PMethodWrapperTrampoline;
  93. begin
  94. EnterCriticalSection(CritObjectInstance);
  95. try
  96. if not(assigned(TrampolineFreeList)) then
  97. begin
  98. NewBlock:=VirtualAlloc(nil,SizeOfPage,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  99. NewBlock^.UsageCount:=0;
  100. NewBlock^.Next:=WrapperBlockList;
  101. WrapperBlockList:=NewBlock;
  102. Trampoline:=@NewBlock^.Trampolines;
  103. while pointer(Trampoline)+sizeof(Trampoline)<pointer(NewBlock)+SizeOfPage do
  104. begin
  105. Trampoline^.Next:=TrampolineFreeList;
  106. Trampoline^.Block:=NewBlock;
  107. TrampolineFreeList:=Trampoline;
  108. inc(Trampoline);
  109. end;
  110. end;
  111. Trampoline:=TrampolineFreeList;
  112. TrampolineFreeList:=TrampolineFreeList^.Next;
  113. // inc(Trampoline^.Block^.UsageCount);
  114. Trampoline^.Call:=$e8;
  115. Trampoline^.CallOffset:=pointer(@get_method_offset)-pointer(@Trampoline^.Call)-5;
  116. Trampoline^.Jmp:=$e9;
  117. Trampoline^.JmpOffset:=pointer(@TrampolineWndProc)-pointer(@Trampoline^.Jmp)-5;
  118. Trampoline^.Method:=Method;
  119. Result:=Trampoline;
  120. finally
  121. LeaveCriticalSection(CritObjectInstance);
  122. end;
  123. end;
  124. procedure FreeObjectInstance(ObjectInstance: Pointer);
  125. begin
  126. EnterCriticalSection(CritObjectInstance);
  127. try
  128. // block gets overwritten by method dec(PMethodWrapperTrampoline(ObjectInstance)^.Block^.UsageCount);
  129. PMethodWrapperTrampoline(ObjectInstance)^.Next:=TrampolineFreeList;
  130. TrampolineFreeList:=PMethodWrapperTrampoline(ObjectInstance);
  131. finally
  132. LeaveCriticalSection(CritObjectInstance);
  133. end;
  134. end;
  135. procedure DeleteInstBlockList;
  136. var
  137. hp : PWrapperBlock;
  138. begin
  139. EnterCriticalSection(CritObjectInstance);
  140. try
  141. while assigned(WrapperBlockList) do
  142. begin
  143. hp:=WrapperBlockList^.Next;
  144. if VirtualFree(WrapperBlockList,4096,MEM_DECOMMIT) then
  145. VirtualFree(WrapperBlockList,0,MEM_RELEASE);
  146. WrapperBlockList:=hp;
  147. end;
  148. finally
  149. LeaveCriticalSection(CritObjectInstance);
  150. end;
  151. end;
  152. function AllocateHWnd(Method: TWndMethod): HWND;
  153. begin
  154. { dummy }
  155. runerror(217);
  156. Result:=0;
  157. end;
  158. procedure DeallocateHWnd(Wnd: HWND);
  159. begin
  160. { dummy }
  161. runerror(217);
  162. end;
  163. initialization
  164. WrapperBlockList:=nil;
  165. TrampolineFreeList:=nil;
  166. InitCriticalSection(CritObjectInstance);
  167. CommonInit;
  168. finalization
  169. CommonCleanup;
  170. DeleteInstBlockList;
  171. DoneCriticalSection(CritObjectInstance);
  172. end.