//
// File: myloop.cpp
//
// Modification history:
//$ FA(24/04/2001): Set compiler bounds-checking option
//$ FA(06/06/2001): Includes baselib.h
//$ FA(19/06/2001): Debugger integration. Close debugger's channel in CloseMachine()
//
//$ LB(20/06/2001): Added Socks 5 parameters management (username and password) in usm.ini parsing
//$ FA(03/06/2001): Replace vsprintf() by _vsnprintf()
//$ FA(18/07/2001): Include codec.h
//
//$ ER(27/07/2001): Add SCsetuser function (does nothing)
//$ FA(31/07/2001): Integrate new console!
//$ FA(03/08/2001): Promoted to C++ file
//$ FA(03/08/2001): Add MMputs() function to allow DLLs to send strings of any length to the log
//$ FA(23/08/2001): Export EndScolMachine(). Exclude the console on the server release
//$ FA(24/08/2001): Move 'nbhook = 0' from WM_SCOLEND case in WindowProc() to EndScolMachine()
//$ FA(14/09/2001): Rewrite StartHTTP() function. The browser is opened inside a thread
//$ FA(12/11/2001): Replace SCOL_DEBUGGER_AWARE by INCLUDE_DEBUGGER
//$ FA(17/01/2002): Call to SCdestroychannel() with extra 'notify' argument set to 0
//
//$ LB (30/05/2002) : AnyInstance function : if CLUBHOUSE_SERVER, don't launch any machine is a supervisor has not been launched
//                    and can't launch the supervisor it-self
//
//$ LB (31/05/2002) : EndScolMachine function : commented the #if !defined(SERVER) : Why the Hell a server could not show the console? use the "LogWin" option in usm.ini to control this behaviour!
//
//$LB (31/05/2002) : ScolShowConsole function : a server should be able to show the console, unless the "LogWin" usmini option is set to "no"
//
//$LB (03/06/2002) : regsufix function : don't register .scol suffixes for the clubhouse vm
//
//$ LB (06/06/2002) : MMputs function : allow the server to print logs
//
//$ LB (06/06/2002) : changed codec functions format
//

#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <string.h>
#include <winsock.h>
#include <time.h>

#include <sys/types.h>
#include <io.h>
#include <direct.h>
#include <shlobj.h>

#include "../kernel/baselib.h"
#include "../kernel/debug.h"   //$ FA(19/06/2001)
#include "../kernel/codec.h"   //$ FA(18/07/2001)

//$LB (05/03/2002)
#include "../kernel/include/inetconnect.h"


//#include "console.h"           //$ FA(03/08/2001)
extern "C" {
# include "../kernel/include/vscol.h"
# include "../kernel/include/common.h"
# include "myloop.h"
# include "../kernel/mmemory.h"
# include "../kernel/vm/mbytec.h"
# include "../kernel/listlab.h"
# include "../kernel/loadpak.h"
# include "../kernel/scol.h"
# include "../kernel/scolsys.h"
# include "../kernel/fifo.h"
# include "../kernel/include/socket.h"
//$ LB: use socks protocol interface
# include "../kernel/include/socks.h"
//
# include "../kernel/mainscol.h"
# include "../kernel/scolsign.h"
# include "../kernel/scolobj.h"
# include "winscol.h"
//# include "active.h"
//debug
# include "../kernel/include/proxyhttp.h"
# include "terminal.h"

HWND ActiveXhwnd = NULL;
char hardware3d[128];
HINSTANCE scolDllInstance;
int fstart;
char execpath[1024];
extern int MEM_MAX_SIZE;
//$ FA(24/04/2001): Set runtime-checks compiler option
extern int optionRuntimeChecks;
//
extern int (*CBinit)(mmachine m);

LRESULT CALLBACK WindowProc(HWND hwnd, unsigned msg, UINT wParam, LONG lParam);
int LoadUsmIni(char *cmdline);
int SCfreeDLLs(void);
int SCiniDLLs(void);
int SCregistDLL(char *name,char *fun,char *funclose);
void MMputs(int n, const char* text);
}




#define WM_SCOLEND (WM_USER+10)

HWND hscol=NULL;
HANDLE thisinst;                 // declare as HINSTANCE
//$ FA(31/07/2001)
//Console* theConsole;
//HWND     cwnd;                    // console window handler
//
struct Terminal tcons;
FILE *flog;
int	flaglogwinsup=0;
int flaglogwin=1;
int flaglog;
int flagactiveX;
int flagrefreshIP=1;

char execname[1024];
char execpath2[1024];

HCURSOR   arrowCursor;
void (*EndMachineCB) (int reason)=NULL;

extern int maxsock;
extern char forcedIP[64];

void startscol();
int SPregistPart(char *name,char *param);
int myhtoi(char *q);


int CloseMachine(mmachine m)
{
  int c;

//  MMechostr(1,"closemachine\n");
//$ FA(19/06/2001): Close debugger's channel
#if defined(INCLUDE_DEBUGGER)
  DBGCloseChannel(m);
#endif
//
  while(MMgetglobal(m,OFFSCCHAN)!=NIL)
  {
	  c=MMfetch(m,MMgetglobal(m,OFFSCCHAN)>>1,0);
//$ FA(17/01/2002): Call to SCdestroychannel() with extra 'notify' argument = 0
	  SCdestroychannel(m, c, 0);
//
  }
  MMechostr(MSKDEBUG,"delete servers\n");
  while(MMgetglobal(m,OFFSCSERVER)!=NIL)
  {
	  c=MMfetch(m,MMgetglobal(m,OFFSCSERVER)>>1,0);
	  MMechostr(MSKDEBUG,"close one server\n");
      SCKcloseserver(SCgetsrvsocket(m,c));
	  SCdelserver(m,c);
  }
  return 0;
}


extern "C" __declspec (dllexport) int EndScolMachine(int box)
{
	MMechostr(MSKRUNTIME,"EndScolMachine %d\n",box);  //SH010907
	if (fstart==1)
	{
		fstart =-1;
		CloseMachine(&mscol);   // detruit les canaux et les objets associes
		SCKend();   // detruit la couche reseau winsock
		SCexeEnd(); // mise a jour du fichier de config des executables que Scol peut lancer
		MMechostr(MSKRUNTIME,"SCKend-\n");
		if ((box)&&(flaglogwin))    // s'agit-il d'une runtime error Scol (flag box) ? et si oui, faut-il afficher la boite de dialogue (flaglogwin) ?
		{
//$ LB (31/05/2002) : Why the Hell a server could not show the console? use the "LogWin" option in usm.ini to control this behaviour!
//#if !defined(SERVER)

//            if (theConsole)
//              theConsole->show(); //$ FA(03/08/2001)

            //$ LB (31/05/2002)
			//ShowWindow(tcons.hwnd, SW_SHOW);
			ScolShowConsole();
//#endif
			MessageBox(tcons.hwnd, "RunTime Error", scriptname, MB_OK);
		}
		KillTimer(hscol,1); // detruit le timer 1 minute qui recalcule l'adresse IP
	    MMechostr(MSKRUNTIME,"flagactiveX=%d\n",flagactiveX);  //SH010907
/*		
        if (!flagactiveX) PostMessage(hscol,WM_SCOLEND,0,0);    // si on est en stand alone, on poste un message SCOLEND
		else    // sinon on detruit la machine tout de suite
		{
            //$ FA(24/08/2001): Moved from case WMSCOL_END in WindowProc()
            nbhook = 0;     // reinitialisation des hooks de la windowproc (ceux-ci peuvent pointer vers des dlls liberees)
			MMechostr(MSKDEBUG,"Free Dlls X\n");
			SCfreeDLLs();   // libere les dlls
			MMechostr(MSKDEBUG,"end X\n");
            //if (theConsole) {
            //  delete theConsole; //$ FA(03/08/2001)
			//  cwnd       = NULL; // Note: hscol == cwnd!
            //  theConsole = 0;
            //}
			DestroyWindow(hscol);   // detruit la fenetre de console
            tcons.hwnd = NULL;
			MMechostr(MSKDEBUG,"apres destruction de la consoleX\n");
            flaglog=0;  // arrete l'affichage des logs
			if (flog) fclose(flog); // ferme le fichier de log
//			if (!flagactiveX) PostQuitMessage(0);   // ???? ne peut jamais etre vrai
            
        }*/
        PostMessage(hscol,WM_SCOLEND,0,0);    // si on est en stand alone, on poste un message SCOLEND
	}
	return 0;
}


void MMputs(int n, const char* text)
//$ FA(03/08/2001): Allow user to echo an arbitrary (non-formatted) long string
{
    if (flaglog && (!n || n == MSKRUNTIME || n&MaskEcho)) {

//$ LB (06/06/2002) : allow the server to print logs
//#if !defined(SERVER)
/*
        if (theConsole) {
            uint32 color = 0x000000; // black
            switch (n) {
                case MSKFOO:
                    color = 0xaa0000;
                    break;
                case MSKRUNTIME:
                    color = 0x0000aa;
                    break;
                case MSKWARNING:
                    color = 0x000099;
                    break;
                case MSKTRACE:
                    color = 0x00aa00;
                    break;
                case MSKDEBUG:
                    color = 0x000000;
                    break;
                    
            }
            theConsole->setColor(color);
            theConsole->write(text); //$ FA(03/08/2001)

        }
*/
        if (tcons.hwnd)
            Techostr(&tcons, (char*)text, strlen(text));
//#endif
        if (flog) {
            fprintf(flog, "%s", text);
            fflush(flog);
        }
    }
}


void MMechostr(int n, char *format, ...)
// Echoes a formatted string (truncated at 16K if necessary)
// (Format string should be declared as const char*)
{
    if (flaglog && (!n || n == MSKRUNTIME || n&MaskEcho)) {
        va_list args;
        char buf[16384];
        va_start(args, format);
//$ FA(03/06/2001)
        _vsnprintf(buf, 16384, format, args);
//
        va_end(args);
        MMputs(n, buf);
    }
}


void scolgethost(LONG lParam)
{
//	time_t t;
  
	SCKendhostname(lParam);
//	if (strncmp(inet_ntoa(*(struct in_addr*)&localscolIP),"194.100.1.",10)) maxsock=1000;

/*
	time(&t);
	t-=921762819; if ((t<0)||(t>80000*5)) maxsock=1000;
*/

	if (!fstart)
	{
		KillTimer(tcons.hwnd,1);
		startscol();
	    SetTimer(tcons.hwnd,1,60000,NULL);
	}
}


LRESULT CALLBACK WindowProc(HWND hwnd, unsigned msg, UINT wParam, LONG lParam)
{
    int hSock,k,i,ret;
    int NetEvent,NetError;
	char name[25];


    if ((hwnd!=tcons.hwnd)&&(mscol.tape))
	{
		MMpush(&mscol,MMgetglobal(&mscol,OFFSCCUR));
	}

	for(i=0;i<nbhook;i++)
	{
		if ((msghook[i]==(int)msg)&&(cbhook[i]))
		{
			ret=0;
            k=(*(cbhook[i]))(&mscol,hwnd,msg,wParam,lParam,&ret);
	        tstscoldead(0);
			
            if (!k)
			{
				if ((hwnd!=tcons.hwnd)&&(mscol.tape))
					MMsetglobal(&mscol,OFFSCCUR,MMpull(&mscol));
				return ret;
			}
		}
	}
    switch( msg ) {

    case WM_PAINT:

        if (hwnd==tcons.hwnd)
        {

            ValidateRect(tcons.hwnd,NULL);
            Trepaint(&tcons);
        }
        break;


    case WSA_ASYNC:
        hSock=(int)wParam;
        NetEvent=WSAGETSELECTEVENT(lParam);
        NetError=WSAGETSELECTERROR(lParam);
        if (hSock==socklife)
        {
            if ((NetError)||(NetEvent==FD_CLOSE))
			{
                MMechostr(MSKRUNTIME,"Broken LifeSocket\n");
				EndScolMachine(0);
                break;
			}
        }
        SCOLNetEvent(&mscol,hSock,NetEvent,NetError);
        tstscoldead(17);
        break;

    case WM_DESTROY:
        if ((fstart!=1)||(hwnd!=tcons.hwnd)) break;
        MMechostr(MSKRUNTIME,"Destroyed Scol Machine\n");
        EndScolMachine(0); // sends a WM_SCOLEND message
        //break; //$ FA(12/09/2001): Do not fall through

	case WM_SCOLEND:
        //$ FA(24/08/2001): Move 'nbhook = 0' to EndScolMachine() 
		nbhook=0;        
		SCfreeDLLs();		
        flaglog=0;
		if (flog) fclose(flog);
        //if (theConsole) {
        //    delete theConsole; //$ FA(03/08/2001)
        //    cwnd       = NULL; // Note: hscol == cwnd!
        //    theConsole = 0;
        //}
		//MMechostr(MSKDEBUG,"apres destroy de hscol\n");
        DestroyWindow(hscol);		
        if (!flagactiveX) 
            PostQuitMessage(0);
        //else if (EndMachineCB)
        //    (*EndMachineCB)(mscol.err);
		break;

/*	case WM_POWERBROADCAST:
		MMechostr(MSKDEBUG,"POWERBROADCAST %d (susp=%d query=%d)\n",wParam,PBT_APMSUSPEND,PBT_APMQUERYSUSPEND);
		if (wParam==PBT_APMSUSPEND)
		{
			MMechostr(MSKRUNTIME,"Suspend mode\n");
			EndScolMachine(0);
			break;
		}
        if ((hwnd!=tcons.hwnd)&&(mscol.tape)) MMsetglobal(&mscol,OFFSCCUR,MMpull(&mscol));
//		if ((!ScolSuper)&&(wParam==PBT_APMQUERYSUSPEND)) return BROADCAST_QUERY_DENY;
        return( DefWindowProc( hwnd, msg, wParam, lParam ) );
*/
    case WM_TIMER:
		if (wParam==1)
		{
			if (fstart)
			{
				if (flagrefreshIP) SCKstarthostname(hwnd);
			}
			else
			{
				MMechostr(MSKTRACE,">>end TimeOut\n");
				KillTimer(hwnd,1);
				startscol();
			    SetTimer(tcons.hwnd,1,60000,NULL);
			}
		}
        break;


    case WM_USER:
	{

		switch (LOWORD(wParam))
		{
			case PROXYHTTP_PROCESS_AUTHORIZATIONS :

				PROXYHTTP_ProcessAuthInfos();
				break;
		
			//$LB (21/02/2002) : add threaded INETisConnected function
			//this message has been sended by the thread to make the father know
			//that threaded INETisConnected test has been done
			case RFL_INET_IS_CONNECTED_MSG :

				SCrflINETisConnected_TerminateProcess ((RflInetIsConnectedData_t*)lParam);
				break;
				
		}
		break;
	}
	
    case WSA_GETHOST:
        scolgethost(lParam);
        break;

	case WM_ERASEBKGND:
		if ( GetClassName( hwnd, name, 25 ) )
			if ( !strcmp( "NoBackgroundClass", name ) ||  !strcmp( "NoBackgroundClass2D", name ))
				break;		

    default:
        if ((hwnd!=tcons.hwnd)&&(mscol.tape)) MMsetglobal(&mscol,OFFSCCUR,MMpull(&mscol));
        return( DefWindowProc( hwnd, msg, wParam, lParam ) );
    }

    if ((hwnd!=tcons.hwnd)&&(mscol.tape)) MMsetglobal(&mscol,OFFSCCUR,MMpull(&mscol));
    //return DefWindowProc( hwnd, msg, wParam, lParam );  //$ FA(10/09/2001)
    return 0;
}


int StartUSM(char *tab,char *rights,char *sizestr)
{
    char buf[1024];
//    MMechostr(MSKTRACE,"launching %s %s %s\n",execname,execpath,buf);
	if (tab)
	{
		sprintf(buf,"%s %s %s",tab,rights,sizestr);
	    if (((int)ShellExecute(NULL,"open",execname,buf,execpath2,SW_SHOW))>32) return 0;
	}
	else
	{
	    if (((int)ShellExecute(NULL,"open",execname,"",execpath2,SW_SHOW))>32) return 0;
	}
    return -1;
}


static char url[1024];
static int  askUser  = 0;
static int  launched = 0;


static DWORD openURLThread(void)
{
	char msg[1024];

	sprintf(msg, "Do you want to launch %s?", url);
	if (!askUser || (MessageBox(NULL, msg, "Warning", MB_YESNO|MB_SETFOREGROUND) == IDYES))
		ShellExecute(NULL, "open", url, NULL, execpath2, SW_SHOW);
    launched = 0;
    ExitThread(0);
	return 0;
}


int StartHTTP(char *buf, int ask)
{
    if (strlen(buf) >= 512 || launched)
        return 0;
    DWORD threadId;
    MMechostr(MSKTRACE, "Launching URL %s\n", buf);
    askUser = ask && strncmp(buf, "http://", 7) 
                  && strncmp(buf, "https://", 8)
                  && strncmp(buf, "ftp://", 6)
                  && strncmp(buf, "mailto:", 7);
    strcpy(url, buf);
    launched = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)openURLThread, 0, 0, &threadId) != NULL;
    return 0;
}


int StartExe(char *buf,char *param)
{
	char path[1024];
    MMechostr(MSKTRACE,"launching EXE %s\n",buf);
	ScolGetPath(path,buf);
	ShellExecute(NULL,"open",buf,param,path,SW_SHOWNORMAL);
    return 0;
}

int ScolShowConsole()
{
//$LB (31/05/2002) : a server should be able to show the console, unless the "LogWin" usmini option is set to "no"
//#if !defined(SERVER)
	if (flaglogwin)
//    if (theConsole)
//      theConsole->show(); //$ FA(03/08/2001)
		ShowWindow(tcons.hwnd, SW_SHOW);
//#endif
	return 0;
}

int ScolHideConsole()
{
#if !defined(SERVER)
//    if (theConsole)
//      theConsole->hide(); //$ FA(03/08/2001)
    ShowWindow(tcons.hwnd, SW_HIDE);
#endif
	return 0;
}


int TrySUP()
{
    SOCKADDR_IN ina;
    SOCKET s;
    int k;

    s=socket(PF_INET,SOCK_STREAM,0);
    if (s==INVALID_SOCKET) return -1;
    ina.sin_family = PF_INET;
    ina.sin_port   = htons((short)STDPORT);
    ina.sin_addr.s_addr = SCKbindadress();
    k=bind(s,(struct sockaddr*)&ina,sizeof(ina));
	closesocket((SOCKET)s);
	return k;
}

int FindPaths(LPSTR cmdline)
{
    char* mots[128];
    int  nbmots,i;
    char buf[1024];
    
    scriptname[0]=0;
    if ((cmdline)&&(cmdline[0]))
    {
		if (!strncmp(cmdline,"scol://",7))
		{
			strcpy(scriptname,cmdline);
		}
		else
		{
			strcpy(buf,cmdline);
            nbmots=Mcutting(buf,mots);
            if (nbmots>=1)
			{
				if (mots[0][0]=='"')
				{
					strcpy(scriptname,&(mots[0][1]));
					if (strlen(scriptname)) scriptname[strlen(scriptname)-1]=0;
				}
				else strcpy(scriptname,mots[0]);
			}
            else scriptname[0]=0;
            if (nbmots>=2) SCdefineRights(mots[1]);
            if (nbmots>=3) ScolMemoryLength=atoi(mots[2]);
		}
    }

    scriptcontent[0]='$';
    
    if (scriptname[0]==0)
    {
    }
    else if (scriptname[0]=='$')
    {

        strcpy(buf,scriptname+1);
        i=0;
        while((buf[i])&&(buf[i]!='$')) i++;
        if (buf[i]==0) return -1;
        buf[i]=0;
        strcpy(scriptname,buf);
        strcpy(scriptcontent,&buf[i+1]);
    }
    else if (!strncmp(scriptname,"scol://",7))
    {
		strcpy(scriptcontent,scriptname);
		strcpy(scriptname,"browser");
	}
    else
    {
    }

    GetCurrentDirectory (512,execpath);
    if ((execpath[strlen(execpath)-1]=='\\')||(execpath[strlen(execpath)-1]=='/'))
		execpath[strlen(execpath)-1]=0;
	sprintf(execpath2,"%s\\",execpath);
	sprintf(execname,"%s\\usmwin.exe",execpath);

    return 0;
}

int regsuffix(char *ext,char *reg)
{
//$LB (03/06/2002) : don't register .scol suffixes for the clubhouse vm
#ifndef CLUBHOUSE_SERVER

	HKEY hkey;
	char bufext[512];
	char bufreg[512];
	char directory[512];
	char buffer2[512];

//MessageBox(NULL,ext,"suffix_ext",MB_OK);
//MessageBox(NULL,reg,"suffix_reg",MB_OK);

	sprintf(bufext,"%s",ext);
    RegCreateKey(HKEY_CLASSES_ROOT,bufext, &hkey);
	sprintf(bufreg,"%s",reg);
    RegSetValue(HKEY_CLASSES_ROOT,bufext,REG_SZ,bufreg,strlen(bufreg));

    RegCreateKey(HKEY_CLASSES_ROOT,bufreg, &hkey);
    RegSetValue(HKEY_CLASSES_ROOT,bufreg,REG_SZ,"Script SCOL",strlen("Script SCOL"));

	sprintf(bufreg,"%s\\DefaultIcon",reg);
    RegCreateKey(HKEY_CLASSES_ROOT,bufreg, &hkey);
    GetCurrentDirectory (255,directory);
    if (directory[strlen(directory)-1]=='\\') directory[strlen(directory)-1]=0; 
    sprintf (buffer2,"%s\\usmwin.exe,0",directory);
    RegSetValue(HKEY_CLASSES_ROOT,bufreg,REG_SZ,buffer2,strlen(buffer2));

	sprintf(bufreg,"%s\\shell",reg);
    RegCreateKey(HKEY_CLASSES_ROOT,bufreg, &hkey);
	sprintf(bufreg,"%s\\shell\\open",reg);
    RegCreateKey(HKEY_CLASSES_ROOT,bufreg, &hkey);
    RegSetValue(HKEY_CLASSES_ROOT,bufreg,REG_SZ,"",strlen(""));

	sprintf(bufreg,"%s\\shell\\open\\command",reg);
    RegCreateKey(HKEY_CLASSES_ROOT,bufreg, &hkey);
    sprintf (buffer2,"\"%s\\usmwin.exe\" \"%%1\"",directory);
    RegSetValue(HKEY_CLASSES_ROOT,bufreg,REG_SZ,buffer2,strlen(buffer2));

#endif

	return 0;
}







int regproto(char *proto)
{
    HKEY hkey;
	char buf[512];
	char directory[512];
	char buffer2[512];
    char editflags[4]={2,0,0,0};


//MessageBox(NULL,proto,"proto",MB_OK);

    RegCreateKey(HKEY_CLASSES_ROOT,proto, &hkey);
    RegSetValue(HKEY_CLASSES_ROOT,proto,REG_SZ,"URL : Protocol SCOL",strlen("URL : Protocol SCOL"));
//	  RegOpenKey(hkey,proto,&hkey);

    RegSetValueEx(hkey,"EditFlags",0,REG_BINARY,(unsigned char *)editflags,4);
    RegSetValueEx(hkey,"URL Protocol",0,REG_SZ,(unsigned char *)"",1);
    
	sprintf(buf,"%s\\DefaultIcon",proto);
  	RegCreateKey(HKEY_CLASSES_ROOT,buf, &hkey);
    RegSetValue(HKEY_CLASSES_ROOT,buf,REG_SZ,buffer2,strlen(buffer2));

    sprintf(buf,"%s\\shell",proto);
  	RegCreateKey(HKEY_CLASSES_ROOT,buf, &hkey);
    sprintf(buf,"%s\\shell\\open",proto);
    RegCreateKey(HKEY_CLASSES_ROOT,buf, &hkey);
    RegSetValue(HKEY_CLASSES_ROOT,buf,REG_SZ,"",strlen(""));

    sprintf(buf,"%s\\shell\\open\\command",proto);
    RegCreateKey(HKEY_CLASSES_ROOT,buf, &hkey);
    GetCurrentDirectory (255,directory);
    if (directory[strlen(directory)-1]=='\\') directory[strlen(directory)-1]=0; 
    sprintf (buffer2,"\"%s\\usmwin.exe\" %%1",directory);
    RegSetValue(HKEY_CLASSES_ROOT,buf,REG_SZ,buffer2,strlen(buffer2));

	return 0;
}










void GetNameExt(char *path,char *name,char *ext)
{
	int i,j;

	name[0]=ext[0]=0;
	for (i=strlen(path)-1 ; i>=0 ; i--)
		if (path[i]=='.') break;
	if (i>=0) {
		strcpy(ext,path+i+1);
	}
	for (j=i-1 ; j>=0 ; j--)
		if ((path[j]=='\\') || (path[j]=='/')) break;
	strncpy(name,path+j+1,i-j-1);
	name[i-j-1]=0;
}

int RefreshExe()
{
	FILE *f;
	char *src;
	char *line;
    char buf[1024];
    char* argv[128];
    int n;
	char categ[128];
	ITEMIDLIST * pidl;
	char PrgPath[MAX_PATH];
	char curdir[MAX_PATH];
	char allfiles[MAX_PATH];
	char filename[MAX_PATH];
	char name[MAX_PATH];
	char ext[MAX_PATH];
	long h,res;
	struct _finddata_t fileinfo;
	SHFILEINFO sfi;

	PrgPath[0]=0;

	/* recherche du répertoire "Démarrer->Programmes" */
	CoInitialize(NULL);
	SHGetSpecialFolderLocation(NULL,CSIDL_PROGRAMS,&pidl);
	SHGetPathFromIDList(pidl,PrgPath);
	CoUninitialize();

	if (PrgPath[0]==0)
	{
		return 0;
	}
	
	f=fopen("ext.ini","rb");
	if (f==NULL)
	{
		return 0;
	}
	fseek(f,0,SEEK_END);
	n=ftell(f);
	src=(char*)malloc(n+1);
	fseek(f,0,SEEK_SET);
	src[fread(src,1,n,f)]=0;
	fclose(f);

	CoInitialize(NULL);
	categ[0]=0;
	line=src;
	while(line=stdGetLine(line,buf,1024))
	{
		if (n=strCutting(buf,argv))
		{
			if ((*argv[0]=='[') && (argv[0][strlen(argv[0])-1]==']') && (strlen(argv[0])<sizeof(categ)+2))
			{
				strncpy(categ,argv[0]+1,strlen(argv[0])-2);
				categ[strlen(argv[0])-2]=0;
			}
			else
			if ((n>1)&&(!strcmpi(argv[0],"prog")))
			{
				/* recherche des exe et lnk du groupe de programmes voulu */
				sprintf(curdir,"%s\\%s",PrgPath,argv[1]);
				sprintf(allfiles,"%s\\*.*",curdir);
				h=_findfirst(allfiles,&fileinfo);
				res=h;
				while(res!=-1)
				{
					sprintf(filename,"%s\\%s",curdir,fileinfo.name);
					if (!(fileinfo.attrib&16) && strlen(fileinfo.name)>4)
					{
						GetNameExt(fileinfo.name,name,ext);
						if (!stricmp(ext,"lnk") || !stricmp(ext,"exe"))
						{
							SHGetFileInfo(filename,0,&sfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME);
							SCexeAdd(1,categ,sfi.szDisplayName,filename);
						}
					}
					res=_findnext(h,&fileinfo);
				}
				if (h!=-1) _findclose(h);
			}
			else
			if ((n>2)&&(!strcmpi(argv[0],"exe")))
			{
				SCexeAdd(1,categ,argv[1],argv[2]);
			}
			else
			if ((n>1)&&(!strcmpi(argv[0],"delexe")))
			{
				SCexeDel(categ,argv[1]);
			}
		}
    }
	CoUninitialize();
	free((void*)src);
	return 0;
}

int AddExe(char *cat, char *path)
{
	char name[MAX_PATH];
	char name1[MAX_PATH];
	char name2[MAX_PATH];
	char path1[MAX_PATH];
	char path2[MAX_PATH];
	char ext[MAX_PATH];
	FILE *f;
	char *src;
	char *line;
    char buf0[1024],buf[1024];
    char* argv[128];
    int n,flag;
	char categ[128];

	GetNameExt(path,name,ext);
	if (stricmp(ext,"lnk") && stricmp(ext,"exe")) {
		return 1;
	}
	if (SCexeSearch(cat,name)!=NULL) return 1;

	f=fopen("ext.ini","rb");
	if (f==NULL)
	{
		return 1;
	}
	fseek(f,0,SEEK_END);
	n=ftell(f);
	src=(char*)malloc(n+1);
	fseek(f,0,SEEK_SET);
	src[fread(src,1,n,f)]=0;
	fclose(f);

	f=fopen("ext.ini","wb");
	if (f==NULL)
	{
		free((void*)src);
		return 1;
	}
	categ[0]=0;
	line=src;
	flag=0;
	while(line=stdGetLine(line,buf,1024))
	{
		strcpy(buf0,buf);
		if (n=strCutting(buf,argv))
		{
			if ((*argv[0]=='[') && (argv[0][strlen(argv[0])-1]==']') && (strlen(argv[0])<sizeof(categ)+2))
			{
				if (!strcmp(categ,cat)&&(!flag)) {
					*(int*)name1=strlen(name);
					strcpy(name1+sizeof(int),name);
					name2[MBcopyword(name2,(int*)name1)-name2]=0;
					*(int*)path1=strlen(path);
					strcpy(path1+sizeof(int),path);
					path2[MBcopyword(path2,(int*)path1)-path2]=0;
					if (strlen(name2)+strlen(path2)+7 > sizeof(buf)) {
						fclose(f);
						free((void*)src);
						return 1;
					}
					sprintf(buf,"exe %s %s",name2,path2);
					fprintf(f,"%s\n",buf);
					flag=2;
				}
				strncpy(categ,argv[0]+1,strlen(argv[0])-2);
				categ[strlen(argv[0])-2]=0;
			}
			else
			if ((n>1)&&(!strcmpi(argv[0],"delexe"))&&(!strcmp(categ,cat))&&(!strcmp(argv[1],name)))
			{
				flag=1;
			}
		}
		if (flag!=1) {
			fprintf(f,"%s\n",buf0);
		}
		else {
			flag=2;
		}
    }
	if (!flag) {
		*(int*)name1=strlen(name);
		strcpy(name1+sizeof(int),name);
		name2[MBcopyword(name2,(int*)name1)-name2]=0;
		*(int*)path1=strlen(path);
		strcpy(path1+sizeof(int),path);
		path2[MBcopyword(path2,(int*)path1)-path2]=0;
		if (strlen(name2)+strlen(path2)+7 > sizeof(buf)) {
			fclose(f);
			free((void*)src);
			return 1;
		}
		sprintf(buf,"exe %s %s",name2,path2);
		fprintf(f,"%s\n",buf);
	}
	fclose(f);
	SCexeAdd(1,cat,name,path);
	free((void*)src);
	return 0;
}

int DelExe(char *cat, char *name)
{
	char name1[MAX_PATH];
	char name2[MAX_PATH];
	FILE *f;
	char *src;
	char *line;
    char buf0[1024],buf[1024];
    char* argv[128];
    int n,flag;
	char categ[128];

	if (SCexeSearch(cat,name)==NULL) return 1;

	f=fopen("ext.ini","rb");
	if (f==NULL)
	{
		return 1;
	}
	fseek(f,0,SEEK_END);
	n=ftell(f);
	src=(char*)malloc(n+1);
	fseek(f,0,SEEK_SET);
	src[fread(src,1,n,f)]=0;
	fclose(f);

	f=fopen("ext.ini","wb");
	if (f==NULL)
	{
		free((void*)src);
		return 1;
	}
	categ[0]=0;
	line=src;
	flag=0;
	while(line=stdGetLine(line,buf,1024))
	{
		strcpy(buf0,buf);
		if (n=strCutting(buf,argv))
		{
			if ((*argv[0]=='[') && (argv[0][strlen(argv[0])-1]==']') && (strlen(argv[0])<sizeof(categ)+2))
			{
				if (!strcmp(categ,cat)&&(!flag)) {
					*(int*)name1=strlen(name);
					strcpy(name1+sizeof(int),name);
					name2[MBcopyword(name2,(int*)name1)-name2]=0;
					if (strlen(name2)+8 > sizeof(buf)) {
						fclose(f);
						free((void*)src);
						return 1;
					}
					sprintf(buf,"delexe %s",name2);
					fprintf(f,"%s\n",buf);
					flag=2;
				}
				strncpy(categ,argv[0]+1,strlen(argv[0])-2);
				categ[strlen(argv[0])-2]=0;
			}
			else
			if ((n>2)&&(!strcmpi(argv[0],"exe"))&&(!strcmp(categ,cat))&&(!strcmp(argv[1],name)))
			{
				flag=1;
			}
		}
		if (flag!=1) {
			fprintf(f,"%s\n",buf0);
		}
		else {
			flag=2;
		}
    }
	if (!flag) {
		*(int*)name1=strlen(name);
		strcpy(name1+sizeof(int),name);
		name2[MBcopyword(name2,(int*)name1)-name2]=0;
		if (strlen(name2)+8 > sizeof(buf)) {
			fclose(f);
			free((void*)src);
			return 1;
		}
		sprintf(buf,"delexe %s",name2);
		fprintf(f,"%s\n",buf);
	}
	fclose(f);
	SCexeDel(cat,name);
	free((void*)src);
	return 0;
}

//$ LB (06/06/2002) : changed codec functions format
//typedef int (*FCODEC)(char *buf, int size, int (*identify)(char *src, char *dst));
typedef int (*FCODEC)(char *buf, int sizeBuf, int sizeData, int *sizeNeeded, int (*identify)(char *src, char *dst));

int regcodec(char *name)
{
    HINSTANCE hLibrary;
	FCODEC fun;
	
    hLibrary=LoadLibrary(name);
	if (hLibrary)
	{
		fun=(FCODEC)GetProcAddress(hLibrary,"codec");
		if (fun) McodecRegister(fun);
	}
	return 0;
}


int LoadUsmIni(char *cmdline)
{
	FILE *f;
	char src[4096];
	char *line;
    char buf[512];
    char* argv[128];
    char path[1204];
    int n;
	time_t timep;
	struct tm *res;

	SCexeInit();
	HTTPproxy[0]=0;
	//$ LB
	SOCKSsetUsername (NULL);
	SOCKSsetPassword (NULL);
	//end $ LB
	hardware3d[0]=0;
	forcedIP[0]=0;
	f=fopen("usm.ini","rb");
	if (f==NULL)
	{
		return 0;
	}
	src[fread(src,1,4095,f)]=0;
	fclose(f);
	line=src;
	while(line=stdGetLine(line,buf,512))
	{
//		if (flog) MMechostr(MSKDEBUG,"usm.ini : %s\n",buf);
		if (n=strCutting(buf,argv))
		{

			if ((n>1)&&(!strcmpi(argv[0],"port")))
			{
				STDPORT=atoi(argv[1]);
			}
			else if ((n>1)&&(!strcmpi(argv[0],"echo")))
			{
				MaskEcho=myhtoi(argv[1]);
			}
			else if ((n>1)&&(!strcmpi(argv[0],"memorymax")))
			{
				MEM_MAX_SIZE=atoi(argv[1])*256*1024;
			}
			else if ((n>1)&&(!strcmpi(argv[0],"3dhardware"))&&(strlen(argv[1])<128))
			{
				strcpy(hardware3d,argv[1]);
			}
			else if ((n>1)&&(!strcmpi(argv[0],"forcedIP"))&&(strlen(argv[1])<64))
			{
				strcpy(forcedIP,argv[1]);
			}
			else if ((n>1)&&(!strcmpi(argv[0],"HTTPproxy"))&&(strlen(argv[1])<64))
			{
				strcpy(HTTPproxy,argv[1]);
			}
			// $ LB
			else if ((n>1)&&(!strcmpi (argv[0],"Socks5Uname"))&&(strlen(argv[1])<255))
			{
				SOCKSsetUsername (argv[1]);
			}
            else if ((n>1)&&(!strcmpi (argv[0], "Socks5Pword"))&&(strlen (argv[1])<255))
			{
				SOCKSsetPassword (argv[1]);
			}
			//end $ LB
			else if ((n>1)&&(!strcmpi(argv[0],"log")))
			{
				if ((flog)&&(!strcmpi(argv[1],"no")))
				{
					fclose(flog);
					flog=NULL;
				}
				else if ((flog==NULL)&&(!strcmpi(argv[1],"yes")))
				{
					strcpy(path,"log/");
					if (scriptname[0]==0) strcpy(path+strlen(path),"supvisor");
					else strcpy(path+strlen(path),ScolGetName(scriptname));
					time(&timep);
					res=localtime(&timep);
					if (res)
						sprintf(path+strlen(path),"-%d-%02d-%02d_%02d-%02d-%02d.log",
							res->tm_year+1900,res->tm_mon+1,res->tm_mday,
							res->tm_hour,res->tm_min,res->tm_sec);
					flog=fopen(path,"w");
					if (!flog) flog=fopen(path+strlen("log/"),"w");
				}
			}
			else if ((n>1)&&(!strcmpi(argv[0],"refreshIP"))&&(!strcmpi(argv[1],"no")))
			{
				flagrefreshIP=0;
			}
			else if ((n>1)&&(!strcmpi(argv[0],"logwin"))&&(!strcmpi(argv[1],"no")))
			{
				flaglogwin=0;
			}
			else if ((n>1)&&(!strcmpi(argv[0],"supervisor"))&&(!strcmpi(argv[1],"debug")))
			{
				flaglogwinsup=1;
			}
			else if ((n>1)&&(!strcmpi(argv[0],"plugin")))
			{
				if (n<3) argv[2]=NULL;
				if (n<4) argv[3]=NULL;
				SCregistDLL(argv[1],argv[2],argv[3]);
			}
			else if ((n>1)&&(!strcmpi(argv[0],"disk")))
			{
				if (n>2) SPregistPart(argv[1],argv[2]);
				else SPregistPart(argv[1],"");
			}
			else if ((n>2)&&(!strcmpi(argv[0],"suffix")))
			{
				if ((cmdline[0]==0)||(!stricmp (cmdline,"/INSTALL")))
					regsuffix(argv[1],argv[2]);
			}
			else if ((n>1)&&(!strcmpi(argv[0],"proto")))
			{
				if ((cmdline[0]==0)||(!stricmp (cmdline,"/INSTALL")))
					regproto(argv[1]);
			}
			else if ((n>1)&&(!strcmpi(argv[0],"codec_pkg")))
			{
				regcodec(argv[1]);
			}
//$ FA(24/04/2001): Set runtime-checks compiler option
            else if (n > 1 && !strcmpi(argv[0], "runtime-checks")) {
              if (!strcmpi(argv[1], "on"))
                optionRuntimeChecks = 1;
              else if (!strcmpi(argv[1], "off"))
                optionRuntimeChecks = 0;
            }
//
		}
    }

	return 0;
}

void startscol()
{
    if (fstart) return;
	fstart=1;
	if (mainscol()) if (!flagactiveX) PostMessage(hscol,WM_SCOLEND,0,0);
}

/*
static void onConsoleClosed(void)
//$ FA(31/07/2001): Callback to be executed when console is closed
{
    MMechostr(MSKRUNTIME,"VM killed: User closed application's console window\n");
    EndScolMachine(0);
}
*/

static BOOL AnyInstance( HANDLE this_inst, HANDLE prev_inst, int cmdshow, LPSTR cmdline )
{
    FILE *f;

	fstart=0;

//	MessageBox(NULL,cmdline,"ini",MB_OK);
    thisinst=this_inst;
	firstScol=0;
	if (!strcmpi(cmdline,"/autostart"))
	{
		cmdline="";
		firstScol=2;
	}
	CreateMutex(NULL,TRUE,"Scol_first");
	if ((firstScol==0)&&(!GetLastError())) firstScol=1;
    if (FindPaths(cmdline)) return FALSE;
//	MessageBox(NULL,"ok","ini",MB_OK);
    flog=NULL;
	flaglogwin=1;
	flaglogwinsup=0;
	flaglog=1;
	SCiniDLLs();

	McodecInit();

	mt_ini();

	LoadUsmIni(cmdline);
	if (!stricmp (cmdline,"/INSTALL")) return FALSE;



	flaglog=1;
//	if (flagactiveX) _asm { int 3};
/*
*/
//$ FA(03/08/2001): Create the console with the name of the current script as its title
    //theConsole = new Console(scriptname);
    //if (!theConsole)
    //    return FALSE;
    //cwnd = (HWND)theConsole->getWindowHandler();          // for compatibility reasons
    //theConsole->setCloseCallback(&onConsoleClosed);
    if (scriptname[0] == 0 && flaglogwinsup)
        //theConsole->show(); //$ FA(03/08/2001)
        Tiniterm(&tcons, scriptname, SW_SHOW);
    else
		//theConsole->hide(); //$ FA(03/08/2001)
        Tiniterm(&tcons, scriptname, SW_HIDE);
//
    if (!tcons.hwnd)
        return FALSE;
    MMechostr(0,"Log File of Scol Virtual Machine\n%s\n",VERSION_NAME);

    if (SCKinit(tcons.hwnd))
	{ 
		MessageBox(NULL,
			"Tcp-Ip protocol is not installed\nYou need to install it first","Error",0);
//	"Das TCP/IP Protokoll ist nicht auf Ihrem Computer installiert.\nBitte installieren Sie das DFUE-Netzwerk.\nNäheres finden Sie im Handbuch der Jewelcase.","Error",NULL);
	    if (f=fopen("C:\\windows\\help\\windows.chm","r"))
		{
			fclose(f);
		    if (((int)ShellExecute(NULL,"open","hh.exe","windows.chm::/windows_network_addprotocol.htm",NULL,SW_SHOW))>32) return 0;
		}
		return FALSE;
	}
    socklife=-1;

    // Launch the Voy@ger

    if (scriptname[0])
    {
		if (TrySUP()==0)
        {

//$ LB (30/05/2002) : if CLUBHOUSE_SERVER, don't launch machine if supervisor has not already been launched
#ifdef CLUBHOUSE_SERVER

			MMechostr(0, "\n\n!! SCOL WARNING : with this release, a supervisor has to be launched first !! Terminate Scol....\n\n");
			PostMessage(hscol,WM_SCOLEND,0,0);
#else
			if (((int)ShellExecute(NULL,"open",execname,0,execpath2,SW_SHOW))>32)
            {
				Sleep(5000);
				if (TrySUP()==0) Sleep(5000);
            }
		    else ScolShowConsole();
#endif
        }
	}

//$ LB (30/05/2002) : if CLUBHOUSE_SERVER, don't launch the supervisor
#ifdef CLUBHOUSE_SERVER
	else
	{
			MMechostr(0, "\n\n!! SCOL WARNING : this release can't launch a supervisor, !! Terminate Scol....\n\n");
			PostMessage(hscol,WM_SCOLEND,0,0);
	}
#endif

    SCOLInit();
    SetTimer(tcons.hwnd,1,1000,NULL);
    return( TRUE );                       
}

static BOOL FirstInstance(HINSTANCE this_inst)
{
    WNDCLASS    wc;
    BOOL        rc;
	
	arrowCursor = LoadCursor( NULL, IDC_ARROW );

    wc.style = CS_HREDRAW | CS_VREDRAW |CS_OWNDC |CS_DBLCLKS;
    wc.lpfnWndProc = WindowProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = sizeof( DWORD );
    wc.hInstance = this_inst;
    wc.hIcon = LoadIcon(this_inst,"IDI_ICON1" );
    wc.hCursor = arrowCursor;
    wc.hbrBackground = GetSysColorBrush(COLOR_MENU);//COLOR_APPWORKSPACE);//COLOR_BACKGROUND;
    wc.lpszMenuName = "GenericMenu";
    wc.lpszClassName = "GenericClass";
    rc = RegisterClass( &wc );
    wc.hbrBackground = NULL;
    wc.lpszClassName = "NoBackgroundClass";
    rc = rc && RegisterClass( &wc );

    return( rc );
}





/****************************************************************/
/*                                                              */
/* BOOL APIENTRY DllMain                                        */
/*                                                              */
/* dll instance events manegement                               */
/*                                                              */
/****************************************************************/
BOOL APIENTRY DllMain( HANDLE hModule, 
                          DWORD  ul_reason_for_call, 
                          LPVOID lpReserved
					 )
{
    switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
			{ 
			scolDllInstance = (HINSTANCE) hModule;
            break;
        }
		case DLL_THREAD_ATTACH: 
		case DLL_THREAD_DETACH:
			break;
		case DLL_PROCESS_DETACH:
			break;
    }
    return TRUE;
}

 
 



int nmouse=0;;

extern "C" __declspec (dllexport) int SCOLWinMain( HINSTANCE this_inst, HANDLE prev_inst, LPSTR cmdline,
                    int cmdshow,int size )
{
    MSG         msg;
//    MSG         msg1;
    
	extern int WM_TMM;


	CBinit=NULL;
    LocalMessage=NULL;
    ScolMemoryLength=size;
    flagactiveX=0;
    if( !prev_inst ) {
        if( !FirstInstance( this_inst ) ) return( FALSE );
    }
    if( !AnyInstance( this_inst, prev_inst, cmdshow, cmdline ) ) return( FALSE );


    while( GetMessage( &msg, NULL, 0, 0 ) )
    {
//		if ((hscol)&&(msg.message==WM_TMM)) MMechostr(MSKDEBUG,">>>>>TMM\n");
//		if ((hscol)&&(msg.message==WM_MOUSEMOVE)) MMechostr(MSKDEBUG,">>>>>MOUSEMOVE %d %d\n",nmouse++,GetTickCount());
/*		if ((hscol)&&(PeekMessage(&msg1,hscol,WM_MOUSEMOVE,WM_MOUSEMOVE,PM_NOREMOVE)))
			MMechostr(MSKDEBUG,">>>>>pending\n");
*/
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }
    return( msg.wParam );
}


extern "C" __declspec (dllexport) int SCOLWinMainActiveX( HINSTANCE this_inst, HINSTANCE prev_inst, LPSTR cmdline,
                    int cmdshow, int (*cbinit)(mmachine m),int size,HWND axhwnd,int (*cbmes)(char * buf))
{
    char MyPath [1024];
    long msize;
    int i;
	  
    //_asm {int 3}
    CBinit=cbinit;
    LocalMessage=cbmes;
    if (size) ScolMemoryLength=size;
    flagactiveX=1;
    
    ActiveXhwnd=axhwnd;

    msize=1024;
    RegQueryValue(HKEY_CLASSES_ROOT,"scol_file\\shell\\open\\command",MyPath,&msize);
    i=msize;
    while (i && (MyPath[i]!='\\') && (MyPath[i]!='/')) i--;

    if (MyPath[i]=='\\' || MyPath[i]=='/') 
    {
      MyPath[i+1]=0;
      if (MyPath[0]=='"') SetCurrentDirectory (MyPath+1);
      else SetCurrentDirectory (MyPath);
    }

    FirstInstance( this_inst );
    if( !AnyInstance( this_inst, prev_inst, cmdshow, cmdline ) ) 
    {
      MessageBox(NULL,"Cannot open the ActiveX","ERROR",0);
      return( FALSE );
    }

 
   return (VERSION_N);
}


extern "C" __declspec (dllexport) int ScolStart(HINSTANCE this_inst,LPSTR cmdline,int cmdshow,int size,int (*cb)(char *buf) )
{
  LocalMessage = cb;
  SCOLWinMain(this_inst, NULL, cmdline, cmdshow, size);
  return 0;
}

extern "C" __declspec (dllexport) void CBEndScol(void (*cb)(int reason) )
{
  EndMachineCB = cb;
//$ FA(07/09/2001): VM should not be destroyed from here!
//EndScolMachine(0);
}

extern "C" __declspec (dllexport) int ScolSendMessage(char *buf)
{
  return SCOLsend(&mscol,buf);
}

extern "C" __declspec (dllexport) char* ScolWritable()
{
  return Firstpack->path;
}

/* SCsetuser here does nothing. This function is used on Linux platform to change the user ID.
   Had to be implemented but nothing to do */
int SCsetuser(mmachine m)
{
  SESETTOP(m, 0, NIL);
  return MERROK;
}