aboutsummaryrefslogblamecommitdiffstats
path: root/Game/Code/Classes/uPluginLoader.pas
blob: f4b6a87a90fe521c4b3ca88181b628432711b710 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16















                                                                      


               


























                                                                                                                                                                         
                                             

                                            
                                         

                                       




                                                          
                                    

                    


                                                                                                  
 


                                                    

                         



                                                                                                                                                                                                                                                                                                       












                                                  
                                    
       



                                                          













                                  



                    




                   

            






                       
                                                               
                
                                                        








                                                                        
                                  
      

             























                                                                    
                                      


                  
      

                                  
         
                     
                                                                                             








                                                            
                                      









                                                                
                                
    
              


                                                       
                                 
        
                                   









                                                                 
                                  


                                                  
             




                                          
                                                 
























                                                                 
                                                             
    
              


                
                                                                
        
                                   










                                            
                                                     



                          
                     
      
                                 

                                          
                        

                                                              
                              


                                               
                             
                        
               
                           
                                                                                                              


                        
                                        


                                               
                                                                   

                            
                                  
















                                                                                               
                                                                                                                                              


                                              
                                                                                                                                                


                                                                       
                                             




                                  
                                                        
                
                                                                    
                                                       
                                                                                                                                 

                                  
                                           












                                                                                                 
                                                                                                                                                


                                                
                                                                                                                                                  









                                                 
                                                                                                                                    




                             
                                                                                                     




                           
                                                                                                             


           
                                                                                                          





                                                  
                                                            

                
                                   
        
                                                                               
          
          
                                                               
             


                      
                           
                                  
           


                                     
                                                                                                                                                  







                                                  
                                                            

                
                                   
        
                                                                               
          
          
                                                               
             


                      
                           



                                            
           


                                     
                                                                                                                                                  







                                                    
                                                     
      
                                   
        
                                       
          

                                                                                     
                                                         
               













                                                                                 
                                                     





                                      
                                     





                                      
                                                                                   
                 
                                                                              
    
                  




                 
                         
        
                     

       
                          
        
                                      
                                    
                                                









                                                
                                                     






                                    
                                                                                   
                 
                                                                                
    
                  



                 
                         
        
                     



                          
                                      






                                    
                                                     



                        
                                                                                                                                                                                                                               
                 

                                                                                 

               
                       
                               
                                                           
          
          
                     
                                                         
             



           
                              


                                            
                                                     
        

                                     
                                                        
                                 

                                                                                                    





                 
                                                                                                                                                                                                
                 

                                                                                  

                
                       
                                
                                       



                                       
                              


                                            
                                                     
        


                                                                 
                                 

                                                                                                     




         





                       
                                                               
                
                                                      








                                                         
                                
      
             








                                                                    
                                    
    

                                                                     


                                                                        
                               
        
                     
                                                                                                     


        
                    




                                           
                                                

                                  
 
          
                                                  
                                                
              

                                                                         
                                                                                                                                                           

             


                                                                                                                                           
             







                                                                                                                                                                                          
           
         











                                                            
                                    
    

                                                                     
      
                  




                                         


                                              

                                                
                                              
            

                                                                       
                                                                                                                                                      

           
                                                                                                                                         




                                                                  
                                                                                                                                                       
         








                                                                
                              
    

                                                                     




                                         
   

                                              
        
                      

                                  
         
       





                                         
unit UPluginLoader;
{*********************
  UPluginLoader
  Unit contains to Classes
    TPluginLoader: Class Searching for and Loading the Plugins
    TtehPlugins:   Class that represents the Plugins in Modules chain
*********************}

interface

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

{$I switches.inc}

uses
  UPluginDefs,
  UCoreModule;

type
  TPluginListItem = record
    Info: TUS_PluginInfo;
    State: Byte; //State of this Plugin: 0 - undefined; 1 - Loaded; 2 - Inited / Running; 4 - Unloaded; 254 - Loading aborted by Plugin; 255 - Unloaded because of Error
    Path: String; //Path to this Plugin
    NeedsDeInit: Boolean; //If this is Inited correctly this should be true
    hLib: THandle; //Handle of Loaded Libary
    Procs: record //Procs offered by Plugin. Don't call this directly use wrappers of TPluginLoader
      Load:   Func_Load;
      Init:   Func_Init;
      DeInit: Proc_DeInit;
    end;
  end;
  {*********************
    TPluginLoader
    Class Searches for Plugins and Manages loading and unloading
  *********************}
  PPluginLoader = ^TPluginLoader;
  TPluginLoader = class (TCoreModule)
    private
      LoadingProcessFinished: Boolean;
      sUnloadPlugin:    THandle;
      sLoadPlugin:      THandle;
      sGetPluginInfo:   THandle;
      sGetPluginState:  THandle;

      procedure FreePlugin(Index: Cardinal);
    public
      PluginInterface: TUS_PluginInterface;
      Plugins: array of TPluginListItem;

      //TCoreModule methods to inherit
      constructor Create; override;
      procedure Info(const pInfo: PModuleInfo); override;
      function Load: Boolean; override;
      function Init: Boolean; override;
      procedure DeInit; override;
      Destructor Destroy; override;

      //New Methods
      procedure BrowseDir(Path: String);             //Browses the Path at _Path_ for Plugins
      function  PluginExists(Name: String): integer; //If Plugin Exists: Index of Plugin, else -1
      procedure AddPlugin(Filename: String);//Adds Plugin to the Array

      function  CallLoad(Index: Cardinal): integer;
      function  CallInit(Index: Cardinal): integer;
      procedure CallDeInit(Index: Cardinal);

      //Services offered
      function LoadPlugin(wParam: TwParam; lParam: TlParam): integer; //wParam PChar(PluginName/PluginPath) | lParam (if wParam = nil) ID of the Plugin
      function UnloadPlugin(wParam: TwParam; lParam: TlParam): integer; //wParam PChar(PluginName/PluginPath) | lParam (if wParam = nil) ID of the Plugin
      function GetPluginInfo(wParam: TwParam; lParam: TlParam): integer; //If wParam = -1 then (If lParam = nil then get length of Moduleinfo Array. If lparam <> nil then write array of TUS_PluginInfo to address at lparam) else (Get PluginInfo of Plugin with Index(wParam) to Address at lParam)
      function GetPluginState(wParam: TwParam; lParam: TlParam): integer; //If wParam = -1 then (If lParam = nil then get length of Moduleinfo Array. If lparam <> nil then write array of TUS_PluginInfo to address at lparam) else (Return PluginInfo of Plugin with Index(wParam))

  end;

  {*********************
    TtehPlugins
    Class Represents the Plugins in Module Chain.
    It Calls the Plugins Procs and Funcs
  *********************}
  TtehPlugins = class (TCoreModule)
    private
      PluginLoader: PPluginLoader;
    public
      //TCoreModule methods to inherit
      constructor Create; override;
      
      procedure Info(const pInfo: PModuleInfo); override;
      function Load: Boolean; override;
      function Init: Boolean; override;
      procedure DeInit; override;
  end;

const
  {$IFDEF MSWINDOWS}
  PluginFileExtension = '.dll';
  {$ENDIF}
  {$IFDEF LINUX}
  PluginFileExtension = '.so';
  {$ENDIF}
  {$IFDEF DARWIN}
  PluginFileExtension = '.dylib';
  {$ENDIF}

implementation

uses
  UCore,
  UPluginInterface,
{$IFDEF MSWINDOWS}
  windows,
{$ELSE}
  dynlibs,
{$ENDIF}
  UMain,
  SysUtils;

{*********************
  TPluginLoader
  Implentation
*********************}

//-------------
// function that gives some Infos about the Module to the Core
//-------------
procedure TPluginLoader.Info(const pInfo: PModuleInfo);
begin
  pInfo^.Name := 'TPluginLoader';
  pInfo^.Version := MakeVersion(1,0,0,chr(0));
  pInfo^.Description := 'Searches for Plugins, loads and unloads them';
end;

//-------------
// Just the Constructor
//-------------
constructor TPluginLoader.Create;
begin
  inherited;

  //Init PluginInterface
  //Using Methods from UPluginInterface
  PluginInterface.CreateHookableEvent := CreateHookableEvent;
  PluginInterface.DestroyHookableEvent := DestroyHookableEvent;
  PluginInterface.NotivyEventHooks := NotivyEventHooks;
  PluginInterface.HookEvent := HookEvent;
  PluginInterface.UnHookEvent := UnHookEvent;
  PluginInterface.EventExists := EventExists;

  PluginInterface.CreateService := @CreateService;
  PluginInterface.DestroyService := DestroyService;
  PluginInterface.CallService := CallService;
  PluginInterface.ServiceExists := ServiceExists;

  //UnSet Private Var
  LoadingProcessFinished := False;
end;

//-------------
//Is Called on Loading.
//In this Method only Events and Services should be created
//to offer them to other Modules or Plugins during the Init process
//If False is Returned this will cause a Forced Exit
//-------------
function TPluginLoader.Load: Boolean;
begin
  Result := True;

  try
    //Start Searching for Plugins
    BrowseDir(PluginPath);
  except
    Result := False;
    Core.ReportError(integer(PChar('Error Browsing and Loading.')), PChar('TPluginLoader'));
  end;
end;

//-------------
//Is Called on Init Process
//In this Method you can Hook some Events and Create + Init
//your Classes, Variables etc.
//If False is Returned this will cause a Forced Exit
//-------------
function TPluginLoader.Init: Boolean;
begin
  //Just set Prvate Var to true.
  LoadingProcessFinished := True;
  Result := True;
end;

//-------------
//Is Called if this Module has been Inited and there is a Exit.
//Deinit is in backwards Initing Order
//-------------
procedure TPluginLoader.DeInit;
var
  I: integer;
begin
  //Force DeInit
  //If some Plugins aren't DeInited for some Reason o0
  for I := 0 to High(Plugins) do
  begin
    if (Plugins[I].State < 4) then
      FreePlugin(I);
  end;

  //Nothing to do here. Core will remove the Hooks
end;

//-------------
//Is Called if this Module will be unloaded and has been created
//Should be used to Free Memory
//-------------
Destructor TPluginLoader.Destroy;
begin
  //Just save some Memory if it wasn't done now..
  SetLength(Plugins, 0);
  inherited;
end;

//--------------
// Browses the Path at _Path_ for Plugins
//--------------
procedure TPluginLoader.BrowseDir(Path: String);
var
  SR: TSearchRec;
begin
  //Search for other Dirs to Browse
  if FindFirst(Path + '*', faDirectory, SR) = 0 then begin
    repeat
      if (SR.Name <> '.') and (SR.Name <> '..') then
        BrowseDir(Path + Sr.Name + PathDelim);
    until FindNext(SR) <> 0;
  end;
  FindClose(SR);
  
  //Search for Plugins at Path
  if FindFirst(Path + '*' + PluginFileExtension, 0, SR) = 0 then
  begin
    repeat
      AddPlugin(Path + SR.Name);
    until FindNext(SR) <> 0;
  end;
  FindClose(SR);
end;
 
//--------------
// If Plugin Exists: Index of Plugin, else -1
//--------------
function  TPluginLoader.PluginExists(Name: String): integer;
var
  I: integer;
begin
  Result := -1;

  if (Length(Name) <= 32 { =>Length(TUS_PluginInfo.Name)}) then
  begin
    for I := 0 to High(Plugins) do
      if (Plugins[I].Info.Name = Name) then
      begin //Found the Plugin
        Result := I;
        Break;
      end;
  end;
end;
 
//--------------
// Adds Plugin to the Array
//--------------
procedure TPluginLoader.AddPlugin(Filename: String);
var
  hLib: THandle;
  PInfo: Proc_PluginInfo;
  Info: TUS_PluginInfo;
  PluginID: integer;
begin
  if (FileExists(Filename)) then
  begin //Load Libary
    hLib := LoadLibrary(PChar(Filename));
    if (hLib <> 0) then
    begin //Try to get Address of the Info Proc
      PInfo := GetProcAddress (hLib, PChar('USPlugin_Info'));
      if (@PInfo <> nil) then
      begin
        Info.cbSize := SizeOf(TUS_PluginInfo);

        try //Call Info Proc
          PInfo(@Info);
        except
          Info.Name := '';
          Core.ReportError(integer(PChar('Error getting Plugin Info: ' + Filename)), PChar('TPluginLoader'));
        end;

        //Is Name set ?
        if (Trim(Info.Name) <> '') then
        begin
          PluginID := PluginExists(Info.Name);

          if (PluginID > 0) and (Plugins[PluginID].State >=4) then
            PluginID := -1;

          if (PluginID = -1) then
          begin
            //Add new item to array
            PluginID := Length(Plugins);
            SetLength(Plugins, PluginID + 1);

            //Fill with Info:
            Plugins[PluginID].Info := Info;
            Plugins[PluginID].State := 0;
            Plugins[PluginID].Path := Filename;
            Plugins[PluginID].NeedsDeInit := False;
            Plugins[PluginID].hLib := hLib;

            //Try to get Procs
            Plugins[PluginID].Procs.Load   := GetProcAddress (hLib, PChar('USPlugin_Load'));
            Plugins[PluginID].Procs.Init   := GetProcAddress (hLib, PChar('USPlugin_Init'));
            Plugins[PluginID].Procs.DeInit := GetProcAddress (hLib, PChar('USPlugin_DeInit'));

            if (@Plugins[PluginID].Procs.Load = nil) OR (@Plugins[PluginID].Procs.Init = nil) OR (@Plugins[PluginID].Procs.DeInit = nil) then
            begin
              Plugins[PluginID].State := 255;
              FreeLibrary(hLib);
              Core.ReportError(integer(PChar('Can''t get Plugin Procs from Libary: "' + Info.Name + '" ' + Filename)), PChar('TPluginLoader'));
            end;

            //Emulate loading process if this Plugin is loaded to late
            if (LoadingProcessFinished) then
            begin
              CallLoad(PluginID);
              CallInit(PluginID);
            end;
          end
          else if (LoadingProcessFinished = False) then
          begin
            if (Plugins[PluginID].Info.Version < Info.Version) then
            begin //Found newer Version of this Plugin
              Core.ReportDebug(integer(PChar('Found a newer Version of Plugin: ' + String(Info.Name))), PChar('TPluginLoader'));

              //Unload Old Plugin
              UnloadPlugin(PluginID, nil);

              //Fill with new Info
              Plugins[PluginID].Info := Info;
              Plugins[PluginID].State := 0;
              Plugins[PluginID].Path := Filename;
              Plugins[PluginID].NeedsDeInit := False;
              Plugins[PluginID].hLib := hLib;

              //Try to get Procs
              Plugins[PluginID].Procs.Load   := GetProcAddress (hLib, PChar('USPlugin_Load'));
              Plugins[PluginID].Procs.Init   := GetProcAddress (hLib, PChar('USPlugin_Init'));
              Plugins[PluginID].Procs.DeInit := GetProcAddress (hLib, PChar('USPlugin_DeInit'));

              if (@Plugins[PluginID].Procs.Load = nil) OR (@Plugins[PluginID].Procs.Init = nil) OR (@Plugins[PluginID].Procs.DeInit = nil) then
              begin
                FreeLibrary(hLib);
                Plugins[PluginID].State := 255;
                Core.ReportError(integer(PChar('Can''t get Plugin Procs from Libary: "' + Info.Name + '" ' + Filename)), PChar('TPluginLoader'));
              end;
            end
            else
            begin //Newer Version already loaded
              FreeLibrary(hLib);
            end;
          end
          else
          begin
            FreeLibrary(hLib);
            Core.ReportError(integer(PChar('Plugin with this Name already exists: ' + String(Info.Name))), PChar('TPluginLoader'));
          end;
        end
        else
        begin
          FreeLibrary(hLib);
          Core.ReportError(integer(PChar('No name reported: ' + Filename)), PChar('TPluginLoader'));
        end;
      end
      else
      begin
        FreeLibrary(hLib);
        Core.ReportError(integer(PChar('Can''t find Info procedure: ' + Filename)), PChar('TPluginLoader'));
      end;
    end
    else
      Core.ReportError(integer(PChar('Can''t load Plugin Libary: ' + Filename)), PChar('TPluginLoader'));
  end;
end;

//--------------
// Calls Load Func of Plugin with the given Index
//--------------
function  TPluginLoader.CallLoad(Index: Cardinal): integer;
begin
  Result := -2;
  if(Index < Length(Plugins)) then
  begin
    if (@Plugins[Index].Procs.Load <> nil) and (Plugins[Index].State = 0) then
    begin
      try
        Result := Plugins[Index].Procs.Load(@PluginInterface);
      except
        Result := -3;
      End;

      if (Result = 0) then
        Plugins[Index].State := 1
      else
      begin
        FreePlugin(Index);
        Plugins[Index].State := 255;
        Core.ReportError(integer(PChar('Error calling Load function from Plugin: ' + String(Plugins[Index].Info.Name))), PChar('TPluginLoader'));
      end;
    end;
  end;
end;

//--------------
// Calls Init Func of Plugin with the given Index
//--------------
function  TPluginLoader.CallInit(Index: Cardinal): integer;
begin
  Result := -2;
  if(Index < Length(Plugins)) then
  begin
    if (@Plugins[Index].Procs.Init <> nil) and (Plugins[Index].State = 1) then
    begin
      try
        Result := Plugins[Index].Procs.Init(@PluginInterface);
      except
        Result := -3;
      End;
      
      if (Result = 0) then
      begin
        Plugins[Index].State := 2;
        Plugins[Index].NeedsDeInit := True;
      end
      else
      begin
        FreePlugin(Index);
        Plugins[Index].State := 255;
        Core.ReportError(integer(PChar('Error calling Init function from Plugin: ' + String(Plugins[Index].Info.Name))), PChar('TPluginLoader'));
      end;
    end;
  end;
end;

//--------------
// Calls DeInit Proc of Plugin with the given Index
//--------------
procedure TPluginLoader.CallDeInit(Index: Cardinal);
begin
  if(Index < Length(Plugins)) then
  begin
    if (Plugins[Index].State < 4) then
    begin
      if (@Plugins[Index].Procs.DeInit <> nil) and (Plugins[Index].NeedsDeInit) then
        try
          Plugins[Index].Procs.DeInit(@PluginInterface);
        except

        End;

      //Don't forget to remove Services and Subscriptions by this Plugin
      Core.Hooks.DelbyOwner(-1 - Index);

      FreePlugin(Index);
    end;
  end;
end;

//--------------
// Frees all Plugin Sources (Procs and Handles) - Helper for Deiniting Functions
//--------------
procedure TPluginLoader.FreePlugin(Index: Cardinal);
begin
  Plugins[Index].State := 4;
  Plugins[Index].Procs.Load := nil;
  Plugins[Index].Procs.Init := nil;
  Plugins[Index].Procs.DeInit := nil;

  if (Plugins[Index].hLib <> 0) then
    FreeLibrary(Plugins[Index].hLib);
end;



//--------------
// wParam PChar(PluginName/PluginPath) | wParam (if lParam = nil) ID of the Plugin
//--------------
function TPluginLoader.LoadPlugin(wParam: TwParam; lParam: TlParam): integer;
var
  Index: integer;
  sFile: String;
begin
  Result := -1;
  sFile := '';
  //lParam is ID
  if (lParam = nil) then
  begin
    Index := wParam;
  end
  else
  begin //lParam is PChar
    try
      sFile := String(PChar(lParam));
      Index := PluginExists(sFile);
      if (Index < 0) And FileExists(sFile) then
      begin //Is Filename
        AddPlugin(sFile);
        Result := Plugins[High(Plugins)].State;
      end;
    except
      Index := -2;
    end;
  end;


  if (Index >= 0) and (Index < Length(Plugins)) then
  begin
    AddPlugin(Plugins[Index].Path);
    Result := Plugins[Index].State;
  end;
end;

//--------------
// wParam PChar(PluginName/PluginPath) | wParam (if lParam = nil) ID of the Plugin
//--------------
function TPluginLoader.UnloadPlugin(wParam: TwParam; lParam: TlParam): integer;
var
  Index: integer;
  sName: String;
begin
  Result := -1;
  //lParam is ID
  if (lParam = nil) then
  begin
    Index := wParam;
  end
  else
  begin //wParam is PChar
    try
      sName := String(PChar(lParam));
      Index := PluginExists(sName);
    except
      Index := -2;
    end;
  end;


  if (Index >= 0) and (Index < Length(Plugins)) then
      CallDeInit(Index)
end;

//--------------
// if wParam = -1 then (if lParam = nil then get length of Moduleinfo Array. if lparam <> nil then write array of TUS_PluginInfo to address at lparam) else (Get PluginInfo of Plugin with Index(wParam) to Address at lParam)
//--------------
function TPluginLoader.GetPluginInfo(wParam: TwParam; lParam: TlParam): integer;
var I: integer;
begin
  Result := 0;
  if (wParam > 0) then
  begin //Get Info of 1 Plugin
    if (lParam <> nil) and (wParam < Length(Plugins)) then
    begin
      try
        Result := 1;
        PUS_PluginInfo(lParam)^ := Plugins[wParam].Info;
      except

      End;
    end;
  end
  else if (lParam = nil) then
  begin //Get Length of Plugin (Info) Array
    Result := Length(Plugins);
  end
  else //Write PluginInfo Array to Address in lParam
  begin
    try
      for I := 0 to high(Plugins) do
        PAUS_PluginInfo(lParam)^[I] := Plugins[I].Info;
      Result := Length(Plugins);
    except
      Core.ReportError(integer(PChar('Could not write PluginInfo Array')), PChar('TPluginLoader'));
    End;
  end;

end;

//--------------
// if wParam = -1 then (if lParam = nil then get length of Plugin State Array. if lparam <> nil then write array of Byte to address at lparam) else (Return State of Plugin with Index(wParam))
//--------------
function TPluginLoader.GetPluginState(wParam: TwParam; lParam: TlParam): integer;
var I: integer;
begin
  Result := -1;
  if (wParam > 0) then
  begin //Get State of 1 Plugin
    if (wParam < Length(Plugins)) then
    begin
      Result := Plugins[wParam].State;
    end;
  end
  else if (lParam = nil) then
  begin //Get Length of Plugin (Info) Array
    Result := Length(Plugins);
  end
  else //Write PluginInfo Array to Address in lParam
  begin
    try
      for I := 0 to high(Plugins) do
        Byte(Pointer(integer(lParam) + I)^) := Plugins[I].State;
      Result := Length(Plugins);
    except
      Core.ReportError(integer(PChar('Could not write PluginState Array')), PChar('TPluginLoader'));
    End;
  end;
end;


{*********************
  TtehPlugins
  Implentation
*********************}

//-------------
// function that gives some Infos about the Module to the Core
//-------------
procedure TtehPlugins.Info(const pInfo: PModuleInfo);
begin
  pInfo^.Name := 'TtehPlugins';
  pInfo^.Version := MakeVersion(1,0,0,chr(0));
  pInfo^.Description := 'Module executing the Plugins!';
end;

//-------------
// Just the Constructor
//-------------
constructor TtehPlugins.Create;
begin
  inherited;
  PluginLoader := nil;
end;

//-------------
//Is Called on Loading.
//In this Method only Events and Services should be created
//to offer them to other Modules or Plugins during the Init process
//If False is Returned this will cause a Forced Exit
//-------------
function TtehPlugins.Load: Boolean;
var
  i: integer; //Counter
  CurExecutedBackup: integer; //backup of Core.CurExecuted Attribute
begin
  //Get Pointer to PluginLoader
  PluginLoader := PPluginLoader(Core.GetModulebyName('TPluginLoader'));
  if (PluginLoader = nil) then
  begin
    Result := false;
    Core.ReportError(integer(PChar('Could not get Pointer to PluginLoader')), PChar('TtehPlugins'));
  end
  else
  begin
    Result := true;

    //Backup CurExecuted
    CurExecutedBackup := Core.CurExecuted;

    //Start Loading the Plugins
    for i := 0 to High(PluginLoader.Plugins) do
    begin
      Core.CurExecuted := -1 - i;

      try
        //Unload Plugin if not correctly Executed
        if (PluginLoader.CallLoad(i) <> 0) then
        begin
          PluginLoader.CallDeInit(i);
          PluginLoader.Plugins[i].State := 254; //Plugin asks for unload
          Core.ReportDebug(integer(PChar('Plugin Selfabort during loading process: ' + String(PluginLoader.Plugins[i].Info.Name))), PChar('TtehPlugins'));
        end
        else
        begin
          Core.ReportDebug(integer(PChar('Plugin loaded succesful: ' + String(PluginLoader.Plugins[i].Info.Name))), PChar('TtehPlugins'));
        end;
      except
        //Plugin could not be loaded.
        // => Show Error Message, then ShutDown Plugin
        on E: Exception do
        begin
          PluginLoader.CallDeInit(i);
          PluginLoader.Plugins[i].State := 255; //Plugin causes Error
          Core.ReportError(integer(PChar('Plugin causes Error during loading process: ' + PluginLoader.Plugins[i].Info.Name + ', ErrorMsg: "' + E.Message + '"')), PChar('TtehPlugins'));
        end;
      end;
    end;

    //Reset CurExecuted  
    Core.CurExecuted := CurExecutedBackup;
  end;
end;

//-------------
//Is Called on Init Process
//In this Method you can Hook some Events and Create + Init
//your Classes, Variables etc.
//If False is Returned this will cause a Forced Exit
//-------------
function TtehPlugins.Init: Boolean;
var
  i: integer; //Counter
  CurExecutedBackup: integer; //backup of Core.CurExecuted Attribute
begin
  Result := true;

  //Backup CurExecuted
  CurExecutedBackup := Core.CurExecuted;

  //Start Loading the Plugins
  for i := 0 to High(PluginLoader.Plugins) do
    try
      Core.CurExecuted := -1 - i;

      //Unload Plugin if not correctly Executed
      if (PluginLoader.CallInit(i) <> 0) then
      begin
        PluginLoader.CallDeInit(i);
        PluginLoader.Plugins[i].State := 254; //Plugin asks for unload
        Core.ReportDebug(integer(PChar('Plugin Selfabort during init process: ' + String(PluginLoader.Plugins[i].Info.Name))), PChar('TtehPlugins'));
      end
      else
        Core.ReportDebug(integer(PChar('Plugin inited succesful: ' + String(PluginLoader.Plugins[i].Info.Name))), PChar('TtehPlugins'));
    except
      //Plugin could not be loaded.
      // => Show Error Message, then ShutDown Plugin
      PluginLoader.CallDeInit(i);
      PluginLoader.Plugins[i].State := 255; //Plugin causes Error
      Core.ReportError(integer(PChar('Plugin causes Error during init process: ' + String(PluginLoader.Plugins[i].Info.Name))), PChar('TtehPlugins'));
    end;

  //Reset CurExecuted
  Core.CurExecuted := CurExecutedBackup;
end;

//-------------
//Is Called if this Module has been Inited and there is a Exit.
//Deinit is in backwards Initing Order
//-------------
procedure TtehPlugins.DeInit;
var
  i: integer; //Counter
  CurExecutedBackup: integer; //backup of Core.CurExecuted Attribute
begin
  //Backup CurExecuted
  CurExecutedBackup := Core.CurExecuted;

  //Start Loop
  
  for i := 0 to High(PluginLoader.Plugins) do
  begin
    try
      //DeInit Plugin
      PluginLoader.CallDeInit(i);
    except
    end;
  end;

  //Reset CurExecuted
  Core.CurExecuted := CurExecutedBackup;
end;

end.