335 lines
8.4 KiB
ObjectPascal
335 lines
8.4 KiB
ObjectPascal
![]() |
|
||
|
{*******************************************************} // 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.
|