/*     
      SCOL ENVIRONMENT . Magma 1.0 . 1996 . Sylvain HUET

         hardload.c : chargement des packages systèmes
*/
// Modification history:
//
//$ FA(13/04/2001): Load base package 
//$ FA(21/05/2001): Integrate debugger
//$ FA(10/07/2001): Load packages 3d registering and display packages
//$ FA(10/07/2001): Load packages 3d registering and display packages
//$ FA(03/08/2001): Add MMputs() function to echo strings of unrestricted length
//$ FA(26/10/2001): Recreate the base environment in a hash table
//$ FA(12/11/2001): Replace SCOL_DEBUGGER_AWARE by INCLUDE_DEBUGGER
//
//$ LB (13/06/2002) : added the OBJgetNewHandler function to the cbmachine
//


 
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <windows.h>

#include "common/kernel.h"
#include "scol.h"
#include "scolSystem.h"
//$ FA(10/07/2001)
#include "3d/display.h"
#include "3d/register.h"
//
#include "OS_specific/windows/winscol.h"
#include "listlab.h"
#include "scolMacros.h"
#include "scolobj.h"
#include "OS_specific/windows/objbitmap.h"
#include "scolCbMachine.h"

extern cbmachine ww;
extern char hardware3d[128];
extern void regX3D(char* name,void* address);
extern int mt_start(int per,int param,int (*fun)(int i,int param));
extern int mt_del(int i);
extern int MX3registerDevice(char *clearname,char *id);
extern int Minterpreter(mmachine m);
extern int Msearchinsyspak(mmachine m, char *name);
extern int tstscoldead(int i);
extern LRESULT CALLBACK WindowProc( HWND hwnd, unsigned msg, UINT wParam, LONG lParam ) ;
extern sysexe SCexeSearch(char *categ, char *name);
extern int SPstorepack(mmachine m);
extern HWND ActiveXhwnd;

void* SCgetExtra(char *funcname)
{
  if (!strcmp(funcname,"hscol")) return hscol;
  if (!strcmp(funcname,"this_inst")) return thisinst;
  if (!strcmp(funcname,"FirstPack")) return Firstpack;
  if (!strcmp(funcname,"free")) return free;
  if (!strcmp(funcname,"3dhardware")) return hardware3d;
  if (!strcmp(funcname,"regX3D")) return regX3D;
  if (!strcmp(funcname,"GRCreateBitmap")) return NULL;
  if (!strcmp(funcname,"GRCreateBitmap8")) return NULL;
  if (!strcmp(funcname,"GRDestroyBitmap")) return NULL;
  if (!strcmp(funcname,"GRGetBitmapSize")) return NULL;
  if (!strcmp(funcname,"GRCopyBitmap")) return NULL;
  if (!strcmp(funcname,"mt_start")) return mt_start;
  if (!strcmp(funcname,"mt_del")) return mt_del;
  if (!strcmp(funcname,"MX3registerDevice")) return MX3registerDevice;
  // added for exteriorisation of lib2d
  if (!strcmp(funcname,"tstscoldead")) return tstscoldead;
  if (!strcmp(funcname,"windowproc")) return WindowProc;
  if (!strcmp(funcname,"scexesearch")) return SCexeSearch;
  if (!strcmp(funcname,"SPstorepack")) return SPstorepack;
  if (!strcmp(funcname,"ActiveXhwnd")) return ActiveXhwnd;
  return NULL;
}

int SCinitCBm(cbmachine w)
{
  w->MMpush=MMpush;
  w->MMpushNoGC=MMpushNoGC;
  w->MMpull=MMpull;
  w->MMgetPP=MMgetPP;
  w->MMsetPP=MMsetPP;
  w->MMget=MMget;
  w->MMset=MMset;
  w->MMgetglobal=MMgetglobal;
  w->MMsetglobal=MMsetglobal;
  w->MMgetbase=MMgetbase;
  w->MMsetbase=MMsetbase;
  w->MMfetch=MMfetch;
  w->MMstore=MMstore;
  w->MMstart=MMstart;
  w->MMsize=MMsize;
  w->MMtype=MMtype;
  w->MMstartstr=MMstartstr;
  w->MMsizestr=MMsizestr;
  w->MMsetsizestr=MMsetsizestr;
  w->MMmalloc=MMmalloc;
  w->MMmallocCLR=MMmallocCLR;
  w->Mpushstrbloc=Mpushstrbloc;
  w->MBdeftab=MBdeftab;
  w->MBstrcat=MBstrcat;
  w->PKhardpak=PKhardpak;
  w->PKloader=PKloader;
  w->SPfindfile=SPfindfile;
  w->SPaddfile=SPaddfile;
  w->SCgetsrvsocket=SCgetsrvsocket;
  w->SCgetsocket=SCgetsocket;
  w->Mcutting=Mcutting;
  w->MMechostr=MMechostr;
  w->fread=fread;
  w->Firstpack=Firstpack;
  w->OBJcreate=OBJcreate;     
  w->OBJaddreflex=OBJaddreflex;  
  w->OBJbeginreflex=OBJbeginreflex;
  w->OBJdel=OBJdel;        
  w->OBJdestroy=OBJdestroy;    
  w->OBJdelTH=OBJdelTH;
  w->OBJcallreflex=OBJcallreflex;
  w->OBJregister=OBJregister;
  w->OBJtypebyname=OBJtypebyname;
  w->OBJdefEvent=OBJdefEvent;
  w->OBJgetUserEvent=OBJgetUserEvent;
  w->SCgetExtra=SCgetExtra;
//w->stdloadJpg=stdloadJpg;
  w->OBJdelTM=OBJdelTM;
  w->OBJfindTH=OBJfindTH;
  w->OBJfindTM=OBJfindTM;
  w->Mpushstrblocn=Mpushstrblocn;
  w->Minterpreter=Minterpreter;
  w->Msearchinsyspak=Msearchinsyspak;
  w->MBstrcatn=MBstrcatn;
  w->Buffer2texture=NULL;
  w->MMputs=MMputs;
  w->OBJgetNewHandler = OBJgetNewHandler;
  return 0;
}
  
typedef int (*FCM)(mmachine,cbmachine);
typedef int (*FCLOSECM)();
struct CBmachine wcb;

//$BB change max dll from 32 to 64
#define NBDLLMAX 64
char namedll[NBDLLMAX][128];
SCOL_PLUGIN_INSTANCE hdll[NBDLLMAX];
int idll;

int SCregistDLL(char* name)
{
	if (idll>=NBDLLMAX)
    return 0;
	
  strcpy(namedll[idll],name);
	idll++;
	return 0;
}

int SCloadDLLs(mmachine m)
{
  int i,k;
  SCOL_PLUGIN_INSTANCE hLibrary;
  FCM SCOLloadDLL;
  
  //$BB Safari navigator change the current dll directory, so we need to change the current dll directory while dll loads
  char dlldir[MAX_PATH];
  GetDllDirectory(MAX_PATH, dlldir);
  SetDllDirectory(execpath2);

  SCinitCBm(&wcb);
	for(i=0;i<idll;i++)
	{
	  MMechostr(0, "################################################################\n");
		MMechostr(0, "[INFOS] Loading %s plugin.\n", namedll[i]);
	  hLibrary=SCOL_PLUGIN_LOAD(namedll[i]);

		hdll[i]=hLibrary;
		if (hLibrary)
		{
			if (SCOLloadDLL = (FCM)SCOL_PLUGIN_GET_SYMBOL(hLibrary, "ScolLoadPlugin"))
			{
				if (k=(*SCOLloadDLL)(m,&wcb))
        {
          MMechostr(0,"[ERROR] An error occurs while loading %s plugin!\n", namedll[i]);
          MMechostr(0, "################################################################\n\n");
          //$BB restore dll directory
          SetDllDirectory(dlldir);
          return k;
        }
        else
        {
          MMechostr(0,"[INFOS] %s plugin successfully loaded.\n", namedll[i]);
          MMechostr(0, "################################################################\n\n");
        }
			}
      else
      {
          MMechostr(0,"[ERROR] An error occurs while loading %s plugin, the symbol entry point \"ScolLoadPlugin\" was not found!\n", namedll[i]);
          MMechostr(0, "################################################################\n\n");
      }
		}
    else
    {
      MMechostr(0,"[ERROR] An error occurs while loading %s plugin, the file does not exits or is invalid!\n", namedll[i]);
      MMechostr(0, "################################################################\n\n");
    }
	}
  //$BB restore dll directory
  SetDllDirectory(dlldir);
  return 0;
}

int SCOLendTimer();
int SCOLfreeHTTP();

int SCfreeDLLs()
{
  int i,k;
  SCOL_PLUGIN_INSTANCE hLibrary;
	FCLOSECM SCOLcloseDLL;
	
  for(i=0;i<idll;i++)
	{
		hLibrary=hdll[i];
		if (hLibrary)
		{
      MMechostr(0, "################################################################\n");
		  MMechostr(0, "[INFOS] Unloading %s plugin.\n", namedll[i]);
      
      SCOLcloseDLL = (FCLOSECM)SCOL_PLUGIN_GET_SYMBOL(hLibrary, "ScolUnloadPlugin");
			if(SCOLcloseDLL != 0)
			{
				if (k=SCOLcloseDLL())
        {
          MMechostr(0, "[ERROR] An error occurs while unloading %s plugin, the memory may not be freed correctly!\n", namedll[i]);
          MMechostr(0, "################################################################\n\n");
          return k;
        }
			}
      else
      {
        MMechostr(0, "[WARNING] No exit point \"ScolUnloadPlugin\" defined for the plugin %s!\n", namedll[i]);
      }
      
      if(SCOL_PLUGIN_UNLOAD(hLibrary))
      {
        MMechostr(0, "[INFOS] %s plugin was correctly unloaded.\n", namedll[i]);
        MMechostr(0, "################################################################\n\n");
      }
      else
      {
        MMechostr(0, "[ERROR] An error occurs while unloading %s plugin, the memory may not be freed correctly!\n", namedll[i]);
        MMechostr(0, "################################################################\n\n");
      }
    }
	}
	SCOLendTimer();
  SCOLfreeHTTP();
  idll=0;
  return 0;
}

int SCiniDLLs()
{
	idll=0;
	return 0;
}

int SCOLloadHTTP(mmachine m);
int SCOLloadHTTPserver(mmachine m);

//$LB (05/03/2002)
int SCOLloadINETCONNECT(mmachine m);

int IniTELNET(mmachine m);

//$BLG: v5.1a1 - Add
int IniUPNP(mmachine m);

int SCOLloadlogger(mmachine m);

int SCOLloadTimer(mmachine m);
int SCOLloadBOX(mmachine m);
int SCOLloadCOLL(mmachine m);

int SCOLloadBN(mmachine m);

//$BLG Start
int SCOLloadWinReg(mmachine m);
//$BLG End

int SCOLloadSYS(mmachine m);
//$ FA(01/11/2000)
int SCOLloadDebug(mmachine m);
//$ FA(13/04/2001): Declaration of base package loader
int SCOLloadBase(mmachine m);
//
int (*CBinit)(mmachine m);



int SCinitsyspack(mmachine m)
{
  int k;

  if (MMpush(m,NIL)) return MERRMEM;
  if (k=SCOLloadHTTP(m)) return k;
  if (k=SCOLloadHTTPserver(m)) return k;
  if (k=SCOLloadTimer(m)) return k;
  if (k=SCOLloadINETCONNECT(m)) return k;
  if (k=SCOLloadlogger(m)) return k;
  if (k=SCOLloadBN(m)) return k;
  if (k=IniTELNET(m)) return k;
  if (k = IniUPNP(m)) return k;
  if (k=SCloadDLLs(m)) return k;
  if (k = SCOLloadWinReg(m)) return k;
  if (k=SCOLloadSYS(m)) return k;
  if (k = SCOLloadDebug(m)) return k;
  if (k = SCOLloadBase(m)) return k;
  if (k = loadPackageDisplay(m)) return k;
  if (k = loadPackageDevice3D(m)) return k;

#if !defined(INCLUDE_DEBUGGER)
  //$BLG - v5.22: Modif
  //SECHECK(createInitialEnvironment(m));
  //$BLG - v5.3.03: Modif (The lckdGC parameter management has been moved to scol.c to encompass the whole init process)
  //m->lckdGC = 1;
  SECHECK(createInitialEnvironment(m));
  //m->lckdGC = 0;
//printInitialEnvironment(m);
#endif

  SECHECK(SEDUP(m));

  if (CBinit) if (k=CBinit(m)) return k;	
  return 0;
}