classes.pp 4.8 KB

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