home *** CD-ROM | disk | FTP | other *** search
/ PC Plus SuperCD (UK) 2000 March / pcp161b.iso / full / delphi / RUNIMAGE / DELPHI30 / SOURCE / RTL / SYS / SYSINIT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-08-04  |  5.9 KB  |  250 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Delphi Runtime Library                          }
  5. {       System Initialization Unit                      }
  6. {                                                       }
  7. {       Copyright (C) 1997 Borland International        }
  8. {                                                       }
  9. {*******************************************************}
  10.  
  11. unit SysInit;
  12.  
  13. interface
  14.  
  15. var
  16.   ModuleIsLib: Boolean;         { True if this module is a dll (a library or a package) }
  17.   ModuleIsPackage: Boolean;     { True if this module is a package }
  18.   TlsIndex: Integer;            { Thread local storage index }
  19.   TlsLast: Byte;                { Set by linker so its offset is last in TLS segment }
  20.   HInstance: Longint;           { Handle of this instance }
  21.   DllProc: Pointer;             { Called whenever DLL entry point is called }
  22.  
  23. procedure _GetTls;
  24. function _InitPkg(Hinst: Longint; Reason: Integer; Resvd: Pointer): LongBool; stdcall;
  25. procedure _InitLib;
  26. procedure _InitExe;
  27.  
  28. implementation
  29.  
  30. const
  31.   kernel = 'kernel32.dll';
  32.  
  33. function FreeLibrary(ModuleHandle: Longint): LongBool; stdcall;
  34.   external kernel name 'FreeLibrary';
  35.  
  36. function GetModuleFileName(Module: Integer; Filename: PChar; Size: Integer): Integer; stdcall;
  37.   external kernel name 'GetModuleFileNameA';
  38.  
  39. function GetModuleHandle(ModuleName: PChar): Integer; stdcall;
  40.   external kernel name 'GetModuleHandleA';
  41.  
  42. function LocalAlloc(flags, size: Integer): Pointer; stdcall;
  43.   external kernel name 'LocalAlloc';
  44.  
  45. function LocalFree(addr: Pointer): Pointer; stdcall;
  46.   external kernel name 'LocalFree';
  47.  
  48. function TlsAlloc: Integer; stdcall;
  49.   external kernel name 'TlsAlloc';
  50.  
  51. function TlsFree(TlsIndex: Integer): Boolean; stdcall;
  52.   external kernel name 'TlsFree';
  53.  
  54. function TlsGetValue(TlsIndex: Integer): Pointer; stdcall;
  55.   external kernel name 'TlsGetValue';
  56.  
  57. function TlsSetValue(TlsIndex: Integer; TlsValue: Pointer): Boolean; stdcall;
  58.   external kernel name 'TlsSetValue';
  59.  
  60. const
  61.   tlsArray      = $2C;    { offset of tls array from FS: }
  62.   LMEM_ZEROINIT = $40;
  63.  
  64. var
  65.   TlsBuffer: Pointer;
  66.   Module: TLibModule = (
  67.     Next: nil;
  68.     Instance: 0;
  69.     ResInstance: 0;
  70.     Reserved: 0);
  71.  
  72. procedure       InitThreadTLS;
  73. var
  74.   p: Pointer;
  75. begin
  76.   if @TlsLast = nil then
  77.     Exit;
  78.   if TlsIndex < 0 then
  79.     RunError(226);
  80.   p := LocalAlloc(LMEM_ZEROINIT, Longint(@TlsLast));
  81.   if p = nil then
  82.     RunError(226)
  83.   else
  84.     TlsSetValue(TlsIndex, p);
  85.   tlsBuffer := p;
  86. end;
  87.  
  88.  
  89. procedure       InitProcessTLS;
  90. var
  91.   i: Integer;
  92. begin
  93.   if @TlsLast = nil then
  94.     Exit;
  95.   i := TlsAlloc;
  96.   TlsIndex := i;
  97.   if i < 0 then
  98.     RunError(226);
  99.   InitThreadTLS;
  100. end;
  101.  
  102.  
  103. procedure       ExitThreadTLS;
  104. var
  105.   p: Pointer;
  106. begin
  107.   if @TlsLast = nil then
  108.     Exit;
  109.   if TlsIndex >= 0 then begin
  110.     p := TlsGetValue(TlsIndex);
  111.     if p <> nil then
  112.       LocalFree(p);
  113.   end;
  114. end;
  115.  
  116.  
  117. procedure       ExitProcessTLS;
  118. begin
  119.   if @TlsLast = nil then
  120.     Exit;
  121.   ExitThreadTLS;
  122.   if TlsIndex >= 0 then
  123.     TlsFree(TlsIndex);
  124. end;
  125.  
  126.  
  127. procedure _GetTls;
  128. asm
  129.         MOV     CL,ModuleIsLib
  130.         MOV     EAX,TlsIndex
  131.         TEST    CL,CL
  132.         JNE     @@isDll
  133.         MOV     EDX,FS:tlsArray
  134.         MOV     EAX,[EDX+EAX*4]
  135.         RET
  136.  
  137. @@initTls:
  138.         CALL    InitThreadTLS
  139.         MOV     EAX,TlsIndex
  140.         PUSH    EAX
  141.         CALL    TlsGetValue
  142.         TEST    EAX,EAX
  143.         JE      @@RTM32
  144.         RET
  145.  
  146. @@RTM32:
  147.         MOV     EAX, tlsBuffer
  148.         RET
  149.  
  150. @@isDll:
  151.         PUSH    EAX
  152.         CALL    TlsGetValue
  153.         TEST    EAX,EAX
  154.         JE      @@initTls
  155. end;
  156.  
  157.  
  158. const
  159.   DLL_PROCESS_DETACH = 0;
  160.   DLL_PROCESS_ATTACH = 1;
  161.   DLL_THREAD_ATTACH  = 2;
  162.   DLL_THREAD_DETACH  = 3;
  163.  
  164.   TlsProc: array [DLL_PROCESS_DETACH..DLL_THREAD_DETACH] of procedure =
  165.     (ExitProcessTLS,InitProcessTLS,InitThreadTLS,ExitThreadTLS);
  166.  
  167. procedure InitializeModule;
  168. var
  169.   FileName: array[0..260] of Char;
  170. begin
  171.   GetModuleFileName(HInstance, FileName, SizeOf(FileName));
  172.   Module.ResInstance := LoadResourceModule(FileName);
  173.   if Module.ResInstance = 0 then Module.ResInstance := Module.Instance;
  174.   RegisterModule(@Module);
  175. end;
  176.  
  177. procedure UninitializeModule;
  178. begin
  179.   UnregisterModule(@Module);
  180.   if Module.ResInstance <> Module.Instance then FreeLibrary(Module.ResInstance);
  181. end;
  182.  
  183. function _InitPkg(Hinst: Longint; Reason: Integer; Resvd: Pointer): Longbool; stdcall;
  184. begin
  185.   ModuleIsLib := True;
  186.   ModuleIsPackage := True;
  187.   Module.Instance := Hinst;
  188.   HInstance := Hinst;
  189.   if @TlsLast <> nil then
  190.     TlsProc[Reason];
  191.   if Reason = DLL_PROCESS_ATTACH then
  192.     InitializeModule
  193.   else if Reason = DLL_PROCESS_DETACH then
  194.     UninitializeModule;
  195.   _InitPkg := True;
  196. end;
  197.  
  198.  
  199. procedure _InitLib;
  200. asm
  201.         { ->    EAX Inittable   }
  202.         {       [EBP+8] Hinst   }
  203.         {       [EBP+12] Reason }
  204.         {       [EBP+16] Resvd  }
  205.  
  206.         MOV     EDX,offset Module
  207.         CMP     dword ptr [EBP+12],DLL_PROCESS_ATTACH
  208.         JNE     @@notInit
  209.  
  210.         PUSH    EAX
  211.         PUSH    EDX
  212.         MOV     ModuleIsLib,1
  213.         MOV     ECX,[EBP+8]
  214.         MOV     HInstance,ECX
  215.         MOV     [EDX].TLibModule.Instance,ECX
  216.         CALL    InitializeModule
  217.         POP     EDX
  218.         POP     EAX
  219.  
  220. @@notInit:
  221.         PUSH    DllProc
  222.         MOV     ECX,offset TlsProc
  223.         CALL    _StartLib
  224. end;
  225.  
  226.  
  227. procedure _InitExe;
  228. asm
  229.         { ->    EAX Inittable   }
  230.  
  231. {       MOV     ModuleIsLib,0   ; zero initialized anyway }
  232.  
  233.         PUSH    EAX
  234.  
  235.         PUSH    0
  236.         CALL    GetModuleHandle
  237.  
  238.         MOV     EDX,offset Module
  239.         PUSH    EDX
  240.         MOV     HInstance,EAX
  241.         MOV     [EDX].TLibModule.Instance,EAX
  242.         CALL    InitializeModule
  243.         POP     EDX
  244.         POP     EAX
  245.  
  246.         CALL    _StartExe
  247. end;
  248.  
  249. end.
  250.