classes.pp 4.8 KB

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