home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / Runimage / Delphi50 / Source / Rtl / Sys / SYSINIT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-11  |  7.7 KB  |  313 lines

  1.  
  2. {*******************************************************}
  3. {                                                       }
  4. {       Borland Delphi Runtime Library                  }
  5. {       System Initialization Unit                      }
  6. {                                                       }
  7. {       Copyright (C) 1997,99 Inprise Corporation       }
  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.   ModuleIsCpp: Boolean;         { True if this module is compiled using C++ Builder }
  19.   TlsIndex: Integer;            { Thread local storage index }
  20.   TlsLast: Byte;                { Set by linker so its offset is last in TLS segment }
  21.   HInstance: LongWord;          { Handle of this instance }
  22.   {$EXTERNALSYM HInstance}
  23.   (*$HPPEMIT 'namespace Sysinit' *)
  24.   (*$HPPEMIT '{' *)
  25.   (*$HPPEMIT 'extern PACKAGE HINSTANCE HInstance;' *)
  26.   (*$HPPEMIT '} /* namespace Sysinit */' *)
  27.   DllProc: Pointer;             { Called whenever DLL entry point is called }
  28.   DataMark: Integer = 0;        { Used to find the virtual base of DATA seg }
  29.  
  30. procedure _GetTls;
  31. function _InitPkg(Hinst: Integer; Reason: Integer; Resvd: Pointer): LongBool; stdcall;
  32. procedure _InitLib;
  33. procedure _InitExe;
  34.  
  35. { Invoked by C++ startup code to allow initialization of VCL global vars }
  36. procedure VclInit(isDLL, isPkg: Boolean; hInst: LongInt; isGui: Boolean); cdecl;
  37. procedure VclExit; cdecl;
  38.  
  39. implementation
  40.  
  41. const
  42.   kernel = 'kernel32.dll';
  43.  
  44. function FreeLibrary(ModuleHandle: Longint): LongBool; stdcall;
  45.   external kernel name 'FreeLibrary';
  46.  
  47. function GetModuleFileName(Module: Integer; Filename: PChar; Size: Integer): Integer; stdcall;
  48.   external kernel name 'GetModuleFileNameA';
  49.  
  50. function GetModuleHandle(ModuleName: PChar): Integer; stdcall;
  51.   external kernel name 'GetModuleHandleA';
  52.  
  53. function LocalAlloc(flags, size: Integer): Pointer; stdcall;
  54.   external kernel name 'LocalAlloc';
  55.  
  56. function LocalFree(addr: Pointer): Pointer; stdcall;
  57.   external kernel name 'LocalFree';
  58.  
  59. function TlsAlloc: Integer; stdcall;
  60.   external kernel name 'TlsAlloc';
  61.  
  62. function TlsFree(TlsIndex: Integer): Boolean; stdcall;
  63.   external kernel name 'TlsFree';
  64.  
  65. function TlsGetValue(TlsIndex: Integer): Pointer; stdcall;
  66.   external kernel name 'TlsGetValue';
  67.  
  68. function TlsSetValue(TlsIndex: Integer; TlsValue: Pointer): Boolean; stdcall;
  69.   external kernel name 'TlsSetValue';
  70.  
  71. function GetCommandLine: PChar; stdcall;
  72.   external kernel name 'GetCommandLineA';
  73.  
  74. const
  75.   tlsArray      = $2C;    { offset of tls array from FS: }
  76.   LMEM_ZEROINIT = $40;
  77.  
  78. var
  79.   TlsBuffer: Pointer;
  80.   Module: TLibModule = (
  81.     Next: nil;
  82.     Instance: 0;
  83.     CodeInstance: 0;
  84.     DataInstance: 0;
  85.     ResInstance: 0;
  86.     Reserved: 0);
  87.  
  88. procedure       InitThreadTLS;
  89. var
  90.   p: Pointer;
  91. begin
  92.   if @TlsLast = nil then
  93.     Exit;
  94.   if TlsIndex < 0 then
  95.     RunError(226);
  96.   p := LocalAlloc(LMEM_ZEROINIT, Longint(@TlsLast));
  97.   if p = nil then
  98.     RunError(226)
  99.   else
  100.     TlsSetValue(TlsIndex, p);
  101.   tlsBuffer := p;
  102. end;
  103.  
  104.  
  105. procedure       InitProcessTLS;
  106. var
  107.   i: Integer;
  108. begin
  109.   if @TlsLast = nil then
  110.     Exit;
  111.   i := TlsAlloc;
  112.   TlsIndex := i;
  113.   if i < 0 then
  114.     RunError(226);
  115.   InitThreadTLS;
  116. end;
  117.  
  118.  
  119. procedure       ExitThreadTLS;
  120. var
  121.   p: Pointer;
  122. begin
  123.   if @TlsLast = nil then
  124.     Exit;
  125.   if TlsIndex >= 0 then begin
  126.     p := TlsGetValue(TlsIndex);
  127.     if p <> nil then
  128.       LocalFree(p);
  129.   end;
  130. end;
  131.  
  132.  
  133. procedure       ExitProcessTLS;
  134. begin
  135.   if @TlsLast = nil then
  136.     Exit;
  137.   ExitThreadTLS;
  138.   if TlsIndex >= 0 then
  139.     TlsFree(TlsIndex);
  140. end;
  141.  
  142.  
  143. procedure _GetTls;
  144. asm
  145.         MOV     CL,ModuleIsLib
  146.         MOV     EAX,TlsIndex
  147.         TEST    CL,CL
  148.         JNE     @@isDll
  149.         MOV     EDX,FS:tlsArray
  150.         MOV     EAX,[EDX+EAX*4]
  151.         RET
  152.  
  153. @@initTls:
  154.         CALL    InitThreadTLS
  155.         MOV     EAX,TlsIndex
  156.         PUSH    EAX
  157.         CALL    TlsGetValue
  158.         TEST    EAX,EAX
  159.         JE      @@RTM32
  160.         RET
  161.  
  162. @@RTM32:
  163.         MOV     EAX, tlsBuffer
  164.         RET
  165.  
  166. @@isDll:
  167.         PUSH    EAX
  168.         CALL    TlsGetValue
  169.         TEST    EAX,EAX
  170.         JE      @@initTls
  171. end;
  172.  
  173.  
  174. const
  175.   DLL_PROCESS_DETACH = 0;
  176.   DLL_PROCESS_ATTACH = 1;
  177.   DLL_THREAD_ATTACH  = 2;
  178.   DLL_THREAD_DETACH  = 3;
  179.  
  180.   TlsProc: array [DLL_PROCESS_DETACH..DLL_THREAD_DETACH] of procedure =
  181.     (ExitProcessTLS,InitProcessTLS,InitThreadTLS,ExitThreadTLS);
  182.  
  183. procedure InitializeModule;
  184. var
  185.   FileName: array[0..260] of Char;
  186. begin
  187.   GetModuleFileName(HInstance, FileName, SizeOf(FileName));
  188.   Module.ResInstance := LoadResourceModule(FileName);
  189.   if Module.ResInstance = 0 then Module.ResInstance := Module.Instance;
  190.   RegisterModule(@Module);
  191. end;
  192.  
  193. procedure UninitializeModule;
  194. begin
  195.   UnregisterModule(@Module);
  196.   if Module.ResInstance <> Module.Instance then FreeLibrary(Module.ResInstance);
  197. end;
  198.  
  199. procedure VclInit(isDLL, isPkg: Boolean; hInst: LongInt; isGui: Boolean); cdecl;
  200. begin
  201.   if isPkg then
  202.   begin
  203.     ModuleIsLib := True;
  204.     ModuleIsPackage := True;
  205.   end else
  206.   begin
  207.     IsLibrary := isDLL;
  208.     ModuleIsLib := isDLL;
  209.     ModuleIsPackage := False; //!!! really unnessesary since DATASEG should be nulled
  210.   end;
  211.   HInstance := hInst;
  212.   Module.Instance := hInst;
  213.   Module.CodeInstance := 0;
  214.   Module.DataInstance := 0;
  215.   ModuleIsCpp := True;
  216.   InitializeModule;
  217.   if not ModuleIsLib then
  218.   begin
  219.     Module.CodeInstance := FindHInstance(@VclInit);
  220.     Module.DataInstance := FindHInstance(@DataMark);
  221.     CmdLine := GetCommandLine;
  222.     IsConsole := not isGui;
  223.   end;
  224. end;
  225.  
  226. procedure VclExit; cdecl;
  227. var
  228.   P: procedure;
  229. begin
  230.   if not ModuleIsLib then
  231.     while ExitProc <> nil do
  232.     begin
  233.       @P := ExitProc;
  234.       ExitProc := nil;
  235.       P;
  236.     end;
  237.   UnInitializeModule;
  238. end;
  239.  
  240. function _InitPkg(Hinst: Longint; Reason: Integer; Resvd: Pointer): Longbool; stdcall;
  241. begin
  242.   ModuleIsLib := True;
  243.   ModuleIsPackage := True;
  244.   Module.Instance := Hinst;
  245.   Module.CodeInstance := 0;
  246.   Module.DataInstance := 0;
  247.   HInstance := Hinst;
  248.   if @TlsLast <> nil then
  249.     TlsProc[Reason];
  250.   if Reason = DLL_PROCESS_ATTACH then
  251.     InitializeModule
  252.   else if Reason = DLL_PROCESS_DETACH then
  253.     UninitializeModule;
  254.   _InitPkg := True;
  255. end;
  256.  
  257.  
  258. procedure _InitLib;
  259. asm
  260.         { ->    EAX Inittable   }
  261.         {       [EBP+8] Hinst   }
  262.         {       [EBP+12] Reason }
  263.         {       [EBP+16] Resvd  }
  264.  
  265.         MOV     EDX,offset Module
  266.         CMP     dword ptr [EBP+12],DLL_PROCESS_ATTACH
  267.         JNE     @@notInit
  268.  
  269.         PUSH    EAX
  270.         PUSH    EDX
  271.         MOV     ModuleIsLib,1
  272.         MOV     ECX,[EBP+8]
  273.         MOV     HInstance,ECX
  274.         MOV     [EDX].TLibModule.Instance,ECX
  275.         MOV     [EDX].TLibModule.CodeInstance,0
  276.         MOV     [EDX].TLibModule.DataInstance,0
  277.         CALL    InitializeModule
  278.         POP     EDX
  279.         POP     EAX
  280.  
  281. @@notInit:
  282.         PUSH    DllProc
  283.         MOV     ECX,offset TlsProc
  284.         CALL    _StartLib
  285. end;
  286.  
  287.  
  288. procedure _InitExe;
  289. asm
  290.         { ->    EAX Inittable   }
  291.  
  292. {       MOV     ModuleIsLib,0   ; zero initialized anyway }
  293.  
  294.         PUSH    EAX
  295.  
  296.         PUSH    0
  297.         CALL    GetModuleHandle
  298.  
  299.         MOV     EDX,offset Module
  300.         PUSH    EDX
  301.         MOV     HInstance,EAX
  302.         MOV     [EDX].TLibModule.Instance,EAX
  303.         MOV     [EDX].TLibModule.CodeInstance,0
  304.         MOV     [EDX].TLibModule.DataInstance,0
  305.         CALL    InitializeModule
  306.         POP     EDX
  307.         POP     EAX
  308.  
  309.         CALL    _StartExe
  310. end;
  311.  
  312. end.
  313.