classes.pp 4.8 KB

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