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