{*******************************************************} // XCL version of SysInit { } // unit. Created Jun-2000 { Borland Delphi Runtime Library } // (C) by Kladov Vladimir { System Initialization Unit } // { } // purpose: make XCL Delphi { Copyright (C) 1997,99 Inprise Corporation } // programs even smaller. { } // {*******************************************************} // Changes are marked as {X} unit SysInit; interface {X} // if your app really need to localize resource, call: {X} procedure UseLocalizeResources; var ModuleIsLib: Boolean; { True if this module is a dll (a library or a package) } ModuleIsPackage: Boolean; { True if this module is a package } ModuleIsCpp: Boolean; { True if this module is compiled using C++ Builder } TlsIndex: Integer; { Thread local storage index } TlsLast: Byte; { Set by linker so its offset is last in TLS segment } HInstance: LongWord; { Handle of this instance } {$EXTERNALSYM HInstance} (*$HPPEMIT 'namespace Sysinit' *) (*$HPPEMIT '{' *) (*$HPPEMIT 'extern PACKAGE HINSTANCE HInstance;' *) (*$HPPEMIT '} /* namespace Sysinit */' *) DllProc: Pointer; { Called whenever DLL entry point is called } DataMark: Integer = 0; { Used to find the virtual base of DATA seg } procedure _GetTls; function _InitPkg(Hinst: Integer; Reason: Integer; Resvd: Pointer): LongBool; stdcall; procedure _InitLib; procedure _InitExe; { Invoked by C++ startup code to allow initialization of VCL global vars } procedure VclInit(isDLL, isPkg: Boolean; hInst: LongInt; isGui: Boolean); cdecl; procedure VclExit; cdecl; implementation {X- moved to System.pas (by A.Torgashin) const kernel = 'kernel32.dll'; function FreeLibrary(ModuleHandle: Longint): LongBool; stdcall; external kernel name 'FreeLibrary'; function GetModuleFileName(Module: Integer; Filename: PChar; Size: Integer): Integer; stdcall; external kernel name 'GetModuleFileNameA'; function GetModuleHandle(ModuleName: PChar): Integer; stdcall; external kernel name 'GetModuleHandleA'; function LocalAlloc(flags, size: Integer): Pointer; stdcall; external kernel name 'LocalAlloc'; function LocalFree(addr: Pointer): Pointer; stdcall; external kernel name 'LocalFree'; function TlsAlloc: Integer; stdcall; external kernel name 'TlsAlloc'; function TlsFree(TlsIndex: Integer): Boolean; stdcall; external kernel name 'TlsFree'; function TlsGetValue(TlsIndex: Integer): Pointer; stdcall; external kernel name 'TlsGetValue'; function TlsSetValue(TlsIndex: Integer; TlsValue: Pointer): Boolean; stdcall; external kernel name 'TlsSetValue'; function GetCommandLine: PChar; stdcall; external kernel name 'GetCommandLineA'; {X+} const tlsArray = $2C; { offset of tls array from FS: } LMEM_ZEROINIT = $40; var TlsBuffer: Pointer; Module: TLibModule = ( Next: nil; Instance: 0; CodeInstance: 0; DataInstance: 0; ResInstance: 0; Reserved: 0); procedure InitThreadTLS; var p: Pointer; begin if @TlsLast = nil then Exit; if TlsIndex < 0 then RunError(226); p := LocalAlloc(LMEM_ZEROINIT, Longint(@TlsLast)); if p = nil then RunError(226) else TlsSetValue(TlsIndex, p); tlsBuffer := p; end; procedure InitProcessTLS; var i: Integer; begin if @TlsLast = nil then Exit; i := TlsAlloc; TlsIndex := i; if i < 0 then RunError(226); InitThreadTLS; end; procedure ExitThreadTLS; var p: Pointer; begin if @TlsLast = nil then Exit; if TlsIndex >= 0 then begin p := TlsGetValue(TlsIndex); if p <> nil then LocalFree(p); end; end; procedure ExitProcessTLS; begin if @TlsLast = nil then Exit; ExitThreadTLS; if TlsIndex >= 0 then TlsFree(TlsIndex); end; procedure _GetTls; asm MOV CL,ModuleIsLib MOV EAX,TlsIndex TEST CL,CL JNE @@isDll MOV EDX,FS:tlsArray MOV EAX,[EDX+EAX*4] RET @@initTls: CALL InitThreadTLS MOV EAX,TlsIndex PUSH EAX CALL TlsGetValue TEST EAX,EAX JE @@RTM32 RET @@RTM32: MOV EAX, tlsBuffer RET @@isDll: PUSH EAX CALL TlsGetValue TEST EAX,EAX JE @@initTls end; const DLL_PROCESS_DETACH = 0; DLL_PROCESS_ATTACH = 1; DLL_THREAD_ATTACH = 2; DLL_THREAD_DETACH = 3; TlsProc: array [DLL_PROCESS_DETACH..DLL_THREAD_DETACH] of procedure = (ExitProcessTLS,InitProcessTLS,InitThreadTLS,ExitThreadTLS); procedure InitializeModule; {X+ var FileName: array[0..260] of Char; X-} begin {X+ GetModuleFileName(HInstance, FileName, SizeOf(FileName)); Module.ResInstance := LoadResourceModule(FileName); if Module.ResInstance = 0 then X-} Module.ResInstance := Module.Instance; RegisterModule(@Module); end; procedure UseLocalizeResources; var FileName: array[0..260] of Char; begin GetModuleFileName(HInstance, FileName, SizeOf(FileName)); Module.ResInstance := LoadResourceModule(FileName); if Module.ResInstance = 0 then Module.ResInstance := Module.Instance; end; procedure UninitializeModule; begin UnregisterModule(@Module); if Module.ResInstance <> Module.Instance then FreeLibrary(Module.ResInstance); end; procedure VclInit(isDLL, isPkg: Boolean; hInst: LongInt; isGui: Boolean); cdecl; begin if isPkg then begin ModuleIsLib := True; ModuleIsPackage := True; end else begin IsLibrary := isDLL; ModuleIsLib := isDLL; ModuleIsPackage := False; //!!! really unnessesary since DATASEG should be nulled end; HInstance := hInst; Module.Instance := hInst; Module.CodeInstance := 0; Module.DataInstance := 0; ModuleIsCpp := True; InitializeModule; if not ModuleIsLib then begin Module.CodeInstance := FindHInstance(@VclInit); Module.DataInstance := FindHInstance(@DataMark); {X CmdLine := GetCommandLine; - converted to a function } IsConsole := not isGui; end; end; procedure VclExit; cdecl; var P: procedure; begin if not ModuleIsLib then while ExitProc <> nil do begin @P := ExitProc; ExitProc := nil; P; end; UnInitializeModule; end; function _InitPkg(Hinst: Longint; Reason: Integer; Resvd: Pointer): Longbool; stdcall; begin ModuleIsLib := True; ModuleIsPackage := True; Module.Instance := Hinst; Module.CodeInstance := 0; Module.DataInstance := 0; HInstance := Hinst; if @TlsLast <> nil then TlsProc[Reason]; if Reason = DLL_PROCESS_ATTACH then InitializeModule else if Reason = DLL_PROCESS_DETACH then UninitializeModule; _InitPkg := True; end; procedure _InitLib; asm { -> EAX Inittable } { [EBP+8] Hinst } { [EBP+12] Reason } { [EBP+16] Resvd } MOV EDX,offset Module CMP dword ptr [EBP+12],DLL_PROCESS_ATTACH JNE @@notInit PUSH EAX PUSH EDX MOV ModuleIsLib,1 MOV ECX,[EBP+8] MOV HInstance,ECX MOV [EDX].TLibModule.Instance,ECX MOV [EDX].TLibModule.CodeInstance,0 MOV [EDX].TLibModule.DataInstance,0 CALL InitializeModule POP EDX POP EAX @@notInit: PUSH DllProc MOV ECX,offset TlsProc CALL _StartLib end; procedure _InitExe; asm { -> EAX Inittable } { MOV ModuleIsLib,0 ; zero initialized anyway } PUSH EAX PUSH 0 CALL GetModuleHandle MOV EDX,offset Module PUSH EDX MOV HInstance,EAX MOV [EDX].TLibModule.Instance,EAX MOV [EDX].TLibModule.CodeInstance,0 MOV [EDX].TLibModule.DataInstance,0 CALL InitializeModule POP EDX POP EAX CALL _StartExe end; end.