//
// 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 (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
//
//$LB (20/03/2005) : change usmwin.exe to scol.exe

#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>

//$BLG - v5.2.06: Add
//#include <Aclapi.h>

#include "baselib.h"
#include "debug.h"   //$ FA(19/06/2001)
#include "codec.h"   //$ FA(18/07/2001)

//$LB (05/03/2002)
#include "common/inetconnect.h"

//$BLG - v5.2.06: Add
#include "compiler/lexer.h"

//#include "console.h"           //$ FA(03/08/2001)
extern "C" {
# include "common/vscol.h"
# include "common/common.h"
# include "OS_specific/windows/myloop.h"
# include "scolMMemory.h"
# include "vm/mbytec.h"
# include "listlab.h"
# include "loadpak.h"
# include "scol.h"
# include "scolSystem.h"
# include "fifo.h"
# include "common/socket.h"
//$ LB: use socks protocol interface
# include "common/socks.h"
//
# include "mainscol.h"
# include "scolsign.h"
# include "scolobj.h"
# include "OS_specific/windows/winscol.h"
//# include "active.h"
//debug
# include "common/proxyhttp.h"
# include "OS_specific/windows/terminal.h"


HWND ActiveXhwnd = NULL;
#define WM_SCOLAXMESS (WM_USER+11)
#define WM_SCOLSETWPTR (WM_USER+12)

char hardware3d[128];
HINSTANCE scolDllInstance;
int fstart;

//$BLG - v5.2.06: Add
int startmode;

//$BB add stand alone mode
int bStandAlone = 0;

char execpath[MAX_PATH];					// Path to scol.exe: path
//$BLG - v5.2.06: Add (Moved from below)
char execname[MAX_PATH];					// Path to scol.exe: path/scol.exe
char execpath2[MAX_PATH];					// Path to scol.exe: path/
//$BLG - v5.2.06: Add
char execsubdir[MAX_PATH];		// Subdir install directory:					path = subpath/subdir
//char cappdatapath[MAX_PATH];	// Path to Common App Data directory: commonappdatapath/subdir
//char cappdatapath2[MAX_PATH];	// Path to Common App Data directory: commonappdatapath/subdir/
char lappdatapath[MAX_PATH];	// Path to Local App Data directory:  localappdatapath/subdir
char lappdatapath2[MAX_PATH];	// Path to Local App Data directory:  localappdatapath/subdir/
char mydcmtspath[MAX_PATH];		// Path to My Documents directory:  	documents/user/mydocuments/subdir
char mydcmtspath2[MAX_PATH];	// Path to My Documents directory:  	documents/user/mydocuments/subdir/
//HRESULT hr_cappdatapath;
HRESULT hr_lappdatapath;
HRESULT hr_mydcmtspath;
bool b_scollocaldir;
bool b_scoluserdir;
char logfilespath[MAX_PATH];	// Path to log files directory:				localappdatapath/subdir
char logfilespath2[MAX_PATH];	// Path to log files directory:				localappdatapath/subdir/
int  maxlogsdirsize;
bool b_scollogsdir;
bool b_logsshouldbeset;
//$BLG - v5.3.03: Add
char execfile[1024];					// VM exe file (for example scol.exe)

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);
//$BLG - v5.2.06: Add
int LoadUsmUserIni(void);

int SCfreeDLLs(void);
int SCiniDLLs(void);
int SCregistDLL(char* name);
void MMputs(int n, const char* text);

//$BLG - v5.2.06: Add
int SCcheckuserini(void);
}

#define WM_SCOLEND (WM_USER+10)

HWND hscol = NULL;
HANDLE thisinst;                 // declare as HINSTANCE

struct Terminal tcons;
FILE *flog;
int	flaglogwinsup = 0;
int flaglogwin = 1;
int flaglog;
int flagactiveX;
int flagrefreshIP = 1;

//$BLG - v5.2.06: Del (Moved above)
//char execname[1024];					// Path to scol.exe: path/scol.exe
//char execpath2[1024];					// Path to scol.exe: path/


HCURSOR   arrowCursor;
extern int maxsock;
extern char forcedIP[64];


void startscol();

//$BLG - v5.2.06: Modif
//int SPregistPart(char *name, char *param);
int SPregistPart(char *name, char *param, int type);

int SPunRegistPart();

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);
  }
  
  //$BB release memory leaks
  SPdesallocpackdir();
  // not here ... but where ^^
  //free((void*)m->tape);

#ifdef _DEBUG
  _CrtDumpMemoryLeaks();
#endif
  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) ?
		{
			ScolShowConsole();
			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
    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))
  {
    if (tcons.hwnd)
      Techostr(&tcons, (char*)text, strlen(text));

    if (flog)
    {
        fprintf(flog, "%s", text);
        fflush(flog);
    }
  }
}

#if defined(SCOL_DEBUG)
void MMechostr(int n, char *format, ...)
// Echoes a formatted string (truncated at 16K if necessary)
// (Format string should be declared as const char*)
// $BLG - v5.21: Modif
// I removed the 16384 limit and increased it to 65536. The reason is that
// the _fooS function has no limit at all. So I don't see why the VM internal
// log write should have a "low" one. Seems to be at least as important as to be
// able to write from a Scol script.
// JFV - : Modif
// Added logtime.
{
  if (flaglog && (!n || n == MSKRUNTIME || n&MaskEcho))
  {
    va_list args;
    //$BLG - v5.21: Modif
    //char buf[16384];
    char buf[65536];

    // Format the date/time of the moment where this message was logged
    struct tm *actualLocalTime;
    time_t actualTime;
    time(&actualTime);
    actualLocalTime = localtime(&actualTime);
    char ftime[65536]= "";

    va_start(args, format);
    //$ FA(03/06/2001)
    //$BLG - v5.21: Modif
    //_vsnprintf(buf, 16384, format, args);
    _vsnprintf(buf, 65536, format, args);
    va_end(args);

    char * ltime = asctime(actualLocalTime);
    ltime[(strlen(ltime)) -2] = '\0';
    
    // add date before message
    if (((buf[(strlen(buf)) -2]) != '\n') && ((buf[(strlen(buf)) -2]) != '\r'))
      sprintf_s(ftime, 65536, "\n%s : %s", ltime, buf);
    else
      sprintf_s(ftime, 65536, "%s : %s", ltime, buf);

    // Send the final log.
    MMputs(n, ftime);
  }
}

#else
void MMechostr(int n, char *format, ...)
// Echoes a formatted string (truncated at 16K if necessary)
// (Format string should be declared as const char*)
//$BLG - v5.21: Modif
//I removed the 16384 limit and increased it to 65536. The reason is that
//the _fooS function has no limit at all. So I don't see why the VM internal
//log write should have a "low" one. Seems to be at least as important as to be
//able to write from a Scol script.
{
    if (flaglog && (!n || n == MSKRUNTIME || n&MaskEcho)) {
        va_list args;
        //$BLG - v5.21: Modif
        //char buf[16384];
        char buf[65536];
        va_start(args, format);
//$ FA(03/06/2001)
        //$BLG - v5.21: Modif
        //_vsnprintf(buf, 16384, format, args);
        _vsnprintf(buf, 65536, format, args);

        va_end(args);
        MMputs(n, buf);
    }
}
#endif

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];

//$BLG
//MMechostr (0, "\nkernel40 WindowProc  hwnd %d   msg %d    wParam %d    lParam %d", (int)hwnd, (int)msg, (int)wParam, (int)lParam);

//#ifdef SCOL_DEBUG
//MMechostr (0, "\nkernel40 WindowProc  hwnd %d   msg %d    wParam %d    lParam %d", (int)hwnd, (int)msg, (int)wParam, (int)lParam);
//#endif

  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;
			//$BLG
			//Note: This is where the custom posted messages are handled, like for Scol Timers or the SERIALIO
			//MMechostr (0, "\ncustom\n");
      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_COPYDATA:
    {
      PCOPYDATASTRUCT cpd;
      cpd = (PCOPYDATASTRUCT)lParam;
      switch( cpd->dwData )
      {
        case WM_SCOLAXMESS:
        {
          char* cmess = (char*) malloc(sizeof(char) * cpd->cbData);
          memcpy(cmess, cpd->lpData, cpd->cbData);
         
          SCOLsend(&mscol, cmess);
          free(cmess);
        }
      }
      break;
    }

    case WM_PAINT:
      if (hwnd == tcons.hwnd)
      {
        ValidateRect(tcons.hwnd, NULL);
        Trepaint(&tcons);
      }
      //$BLG - Add
      /*
      if (wParam)
      	DefWindowProc(hwnd, WM_PRINT, wParam, lParam);
      */
      break;
    
    //$BLG - v5.01: Add  
    //Note: This is the proper solution - Calling WM_PRINTCLIENT and then WM_PRINT (the reverse doesn't work at all)
  	/*
  	case WM_PRINTCLIENT:
  		 //MMechostr(0, "WM_PRINTCLIENT\n");
  		 DefWindowProc(hwnd, WM_PRINT, wParam, lParam);
  	  break;  
    */
    
    //$BLG - v5.01: Add  
    /*
  	case WM_PRINT:
  		//MMechostr(0, "WM_PRINT\n");
  		if (!(lParam & PRF_NONCLIENT)) 
  		 	DefWindowProc(hwnd, WM_PRINTCLIENT, wParam, lParam);
  	  break;  
  	*/
      
  case WSA_ASYNC:
    hSock=(int)wParam;
    NetEvent=WSAGETSELECTEVENT(lParam);
    NetError=WSAGETSELECTERROR(lParam);
    if (hSock==socklife)
    {
      if ((NetError)||(NetEvent==FD_CLOSE))
	    {
        MMechostr(MSKRUNTIME,"\n\nBroken 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);

    //$BB change AX method
    if (flagactiveX && (ActiveXhwnd != NULL))
      PostMessage(ActiveXhwnd, WM_SCOLEND, 0, 0);
    
    DestroyWindow(hscol);
    
    PostQuitMessage(0);
		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()
{
	if (flaglogwin)
		ShowWindow(tcons.hwnd, SW_SHOW);

	return 0;
}

int ScolHideConsole()
{
  if (flaglogwin)
    ShowWindow(tcons.hwnd, SW_HIDE);

  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];
  long msize = 1024;
  
	//$BLG - v5.2.06: Add
	char *ptr;
	TCHAR curpath[MAX_PATH];
  
	//$BLG - v5.2.06: Add
	/*
	LPTSTR FileName = "C:\\ProgramData";
	PSECURITY_DESCRIPTOR pSecurityDescriptor;
  LPBOOL lpbDaclPresent;
  PACL* pDacl;
  LPBOOL lpbDaclDefaulted;
	LPTSTR TrusteeName = "Everyone";
	DWORD AccessMask = GENERIC_READ | GENERIC_WRITE;
	ACCESS_MODE Option = GRANT_ACCESS;
	DWORD InheritFlag = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE; 
	EXPLICIT_ACCESS ExplicitAccess;
	PACL ExistingDacl;
	PACL NewAcl = NULL;
	PSECURITY_DESCRIPTOR psd = NULL;
	DWORD dwError;
	*/


//$BLG - Note: Logs are not activated at this point !!!
//MessageBox(NULL,"0","FindPaths",MB_OK);	

	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]);
		  if (nbmots >= 4)
      {
        ActiveXhwnd = (HWND)(atoi(mots[3]));
        if (ActiveXhwnd != NULL)
          flagactiveX = 1;
      }
		}
	}

  //MessageBox(NULL,"1","FindPaths",MB_OK);	

	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
	{
	}

  //MessageBox(NULL,"2","FindPaths",MB_OK);

	//$BLG - v5.3.03: Add
	
	// execpath, execpath2, execname
  
  //$BB if axmode get scol path from reg
  // not needed with new ax method
  /*
  if (flagactiveX)
  {
    RegQueryValue(HKEY_CLASSES_ROOT, "scol_file\\shell\\open\\command", execname, &msize);
    //MessageBox(NULL, execname, "debug execname before", 0);
    // decal the first "
    sprintf(execname, "%s", (execname+1));
    i = 0;
    while (((i <= msize) && (execname[i]!='\"'))) i++;
    execname[i] = 0;
    //MessageBox(NULL, execname, "debug execname", 0);
  }
  else
  {*/
    //$BB get scol exe from current process
    GetModuleFileName(NULL,execname,MAX_PATH);
    //MessageBox(NULL, execname, "debug execname", 0);
  //}
  
  msize = strlen(execname);
  i = msize;
  while (i && (execname[i]!='\\') && (execname[i]!='/')) i--;
  strncpy(execpath, execname, i);
  //MessageBox(NULL, execpath, "debug execpath", 0);
	//GetCurrentDirectory (512, execpath);
  if ((execpath[strlen(execpath)-1] == '\\') || (execpath[strlen(execpath)-1] == '/'))
	  execpath[strlen(execpath)-1] = 0;
  
  sprintf(execpath2, "%s\\", execpath);
  
  //$LB (20/03/2005) : change usmwin.exe to scol.exe
  //sprintf(execname, "%s\\scol.exe", execpath);
  
	//$BLG - v5.2.06: Add
	//execsubdir
	ptr = strrchr(execpath, '\\');
	if (ptr == NULL)
		ptr = strrchr(execpath, '/');
	if (ptr == NULL)
		execsubdir[0] = 0;
	else
		strncpy(execsubdir, ptr+1, strlen(execpath)+execpath-ptr);
	
	//$BLG - v5.2.06: Add
	/*
	//cappdatapath & cappdatapath2
	cappdatapath[MAX_PATH-1] = 0;
	hr_cappdatapath = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, cappdatapath);
	if (SUCCEEDED(hr_cappdatapath))
	{
		strcat(cappdatapath, "/");
		strcat(cappdatapath, execsubdir);
		strcpy(cappdatapath2, cappdatapath);
		strcat(cappdatapath2, "/");
		//$BLG - Note: Scol root directory in Common App Data is created during Voyager install
	}
	*/
	
	//$BLG - v5.2.06: Add
	/*
	dwError = GetNamedSecurityInfo(cappdatapath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &ExistingDacl, NULL, &psd);
	if (dwError == ERROR_SUCCESS)
	{
		if (ExistingDacl != NULL)
		{
			MessageBox(NULL, "GetNamedSecurityInfo() ok: NTFS partition", "FindPaths", MB_OK);
			SecureZeroMemory(&ExplicitAccess, sizeof(EXPLICIT_ACCESS));
			BuildExplicitAccessWithName(&ExplicitAccess, TrusteeName, AccessMask, Option, InheritFlag);
			
			dwError = SetEntriesInAcl(1, &ExplicitAccess, ExistingDacl, &NewAcl);
			if (dwError == ERROR_SUCCESS)
			{
				MessageBox(NULL, "SetEntriesInAcl() ok", "FindPaths", MB_OK);
				dwError = SetNamedSecurityInfo(cappdatapath, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, NewAcl, NULL);
				if (dwError == ERROR_SUCCESS)
				{
					MessageBox(NULL, "SetNamedSecurityInfo() ok", "FindPaths", MB_OK);
				}
				else
				{
					sprintf(buf, "SetNamedSecurityInfo() failed: %d", dwError);
					MessageBox(NULL, buf, "FindPaths", MB_OK);
				}
			}
			else
			{
				sprintf(buf, "SetEntriesInAcl() failed: %d", dwError);
				MessageBox(NULL, buf, "FindPaths", MB_OK);
			}
		}
		else
			MessageBox(NULL, "GetNamedSecurityInfo() ok: FAT partition", "FindPaths", MB_OK);
		
		//$BLG - v5.2.06: Add
		if (psd != NULL)
			LocalFree(&psd);
	}
	else
	{
		sprintf(buf, "GetNamedSecurityInfo() failed: %d", dwError);
		MessageBox(NULL, buf, "FindPaths", MB_OK);
	}
	*/
	
	//$BLG - v5.2.06: Add
	//lappdatapath & lappdatapath2

	lappdatapath[MAX_PATH-1] = 0;

	//$BB SHGetFolderPath is deprecated // TODO test OS version >= VISTA
	//LPWSTR lwappdata = NULL;
	//hr_lappdatapath = SHGetKnownFolderPath(FOLDERID_LocalAppData, CSIDL_FLAG_CREATE, NULL, &lwappdata);
  
  //$BB add stand alone mode
  if (!bStandAlone)
	  hr_lappdatapath = SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, lappdatapath);

	if (SUCCEEDED(hr_lappdatapath) && !bStandAlone)
	{
		//$BB convert PWSTR to char * // TODO test OS version >= VISTA
		//WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)lwappdata, -1, lappdatapath, sizeof(lappdatapath), NULL, NULL);

		strcat(lappdatapath, "/");
		strcat(lappdatapath, execsubdir);
		strcpy(lappdatapath2, lappdatapath);
		strcat(lappdatapath2, "/");
		//$BLG - Note: Scol root directory in Local App Data isn't necessarily created during Voyager install (Multiple users case)
		GetCurrentDirectory(MAX_PATH, curpath); 
		b_scollocaldir = true;
		if (!SetCurrentDirectory(lappdatapath2))
			b_scollocaldir = (CreateDirectory(lappdatapath2, NULL) == 1);
	  
    //else
    //$BB not else
	  SetCurrentDirectory(curpath);
	}
	
	//$BLG - v5.2.06: Add
	//mydcmtspath & mydcmtspath2
	mydcmtspath[MAX_PATH-1] = 0;
	
	//$BB SHGetFolderPath is deprecated
	//LPWSTR lwdcmts = NULL;
	//hr_mydcmtspath = SHGetKnownFolderPath(FOLDERID_Documents, CSIDL_FLAG_CREATE, NULL, &lwdcmts);
	
  //$BB add stand alone mode
  if (!bStandAlone)
	  hr_mydcmtspath = SHGetFolderPath(NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, mydcmtspath);

	if (SUCCEEDED(hr_mydcmtspath) && !bStandAlone)
	{
		//$BB convert PWSTR to char * // TODO test OS version >= VISTA
		//WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)lwdcmts, -1, mydcmtspath, sizeof(mydcmtspath), NULL, NULL);

		strcat(mydcmtspath, "/");
		strcat(mydcmtspath, execsubdir);
		strcpy(mydcmtspath2, mydcmtspath);
		strcat(mydcmtspath2, "/");
		//$BLG - Note: Scol root directory in Local App Data isn't necessarily created during Voyager install (Multiple users case)
		GetCurrentDirectory(MAX_PATH, curpath); 
		b_scoluserdir = true;
		if (!SetCurrentDirectory(mydcmtspath2))
			b_scoluserdir = (CreateDirectory(mydcmtspath2, NULL) == 1);
			
		//else
    //$BB not else
	  SetCurrentDirectory(curpath);
	}
	
	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 buffer2[1024];
  char scolname[1024];

 //$BB get the current scol.exe name
  scolname[0] = 0;
  /*
  GetCurrentDirectory (255,directory);
  if (directory[strlen(directory)-1]=='\\') directory[strlen(directory)-1]=0;
  //$LB (20/03/2005) : change usmwin.exe to scol.exe
  sprintf (scolname,"%s\\scol.exe,0",directory);
  */
	GetModuleFileName(NULL,scolname,1024); 

  //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);

  sprintf (buffer2,"%s,0",scolname);

  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);
  //$LB (20/03/2005) : change usmwin.exe to scol.exe
  sprintf (buffer2,"\"%s\" \"%%1\"",scolname);
  RegSetValue(HKEY_CLASSES_ROOT,bufreg,REG_SZ,buffer2,strlen(buffer2));

#endif

	return 0;
}


int regproto(char *proto)
{
    HKEY hkey;
	  char buf[512];
	  char buffer2[1024];
    char editflags[4]={2,0,0,0};
    char scolname[1024];

   //$BB get the current scol.exe name
	  scolname[0] = 0;

	  GetModuleFileName(NULL,scolname,1024);

/*    GetCurrentDirectory (255,directory);
      if (directory[strlen(directory)-1]=='\\') directory[strlen(directory)-1]=0;
      //$LB (20/03/2005) : change usmwin.exe to scol.exe
      sprintf (scolname,"%s\\scol.exe,0",directory);
*/

//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);
    sprintf (buffer2,"%s,0",scolname);
    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);
    
    sprintf (buffer2,"\"%s\" \"%%1\"",scolname);
    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;
}


bool GetStandAlone()
{
	FILE *f;
	char src[16385];
	char *line;
  char buf[512];
  char* argv[128];
  int n;

	SCexeInit();
	
	f = fopen("usm.ini", "rb");
	
	if (f == NULL)
	{
		return false;
	}
	
	src[fread(src, 1, 16384, f)] = 0;
	
	fclose(f);
	
	line = src;
	while (line = stdGetLine(line, buf, 512))
	{
		if (n = strCutting(buf, argv))
		{
      if ((n > 1) && (!strcmpi(argv[0], "standalone")))  //stand alone
      {
        if (!strcmpi(argv[1], "yes"))
          bStandAlone = 1;
        return true;
      }
		}
  }

	return false;
}


int LoadUsmIni(char *cmdline)
{
	FILE *f;
	char src[16385];
	char *line;
  char buf[512];
  char* argv[128];
  int n;

	SCexeInit();
	
	f = fopen("usm.ini", "rb");
	
	if (f == NULL)
	{
		return 0;
	}
	
	//$BLG - v5.2.06: Modif
	//src[fread(src, 1, 4095, f)] = 0;
	src[fread(src, 1, 16384, f)] = 0;
	
	fclose(f);
	
	line = src;
	while (line = stdGetLine(line, buf, 512))
	{
		if (n = strCutting(buf, argv))
		{
			if ((n > 1) && (!strcmpi(argv[0], "plugin")))
				SCregistDLL(argv[1]);

			//$BLG - v5.2.06: Modif
      /*
			else if ((n > 1) && (!strcmpi(argv[0], "disk")))
			{
				if (n > 2) SPregistPart(argv[1], argv[2]);
				else SPregistPart(argv[1], "");
			}*/
			else if ((n > 1) && (!strcmpi(argv[0], "cache")))			// Cache
			{
				if (n > 2) SPregistPart(argv[1], argv[2], 0);
				else SPregistPart(argv[1], "", 0);
			}
			else if ((n > 1) && (!strcmpi(argv[0], "disku")))			// User Partition, in My Documents directory
			{
				if (n > 2) SPregistPart(argv[1], argv[2], 1);
				else SPregistPart(argv[1], "", 1);
			}
			else if ((n > 1) && (!strcmpi(argv[0], "diska")))			// Locked App Partition, in Scol install directory
			{
				if (n > 2) SPregistPart(argv[1], argv[2], 2);
				else SPregistPart(argv[1], "", 2);
			}
			
			//$BLG - v5.2.06: Add
      //$BB add stand alone mode
			else if ((n > 1) && (!strcmpi(argv[0], "logsp")))			// Log files directory
			{
				if ((!strncmp(argv[1], "./", 2)) || (!strncmp(argv[1], ".\\", 2)))
          sprintf(logfilespath, "%s%s", bStandAlone ? execpath : lappdatapath, argv[1]+1);
			  else 
			  	strcpy(logfilespath, argv[1]);
			  
			  strcpy(logfilespath2, logfilespath);
			  strcat(logfilespath2, "/");
			  
				if (n > 2)
					a2i(argv[2], &maxlogsdirsize);
				else
					maxlogsdirsize = 0;		//Default: Illimited
			}
			//$BB disable on activeX mode and stand alone mode
			else if ((n > 2) && (!strcmpi(argv[0], "suffix")) && (!bStandAlone) && (!flagactiveX))
			{
				if ((cmdline[0] == 0) || (!stricmp (cmdline, "/INSTALL")))
					regsuffix(argv[1], argv[2]);
			}
      //$BB disable on activeX mode and stand alone mode
			else if ((n > 1) && (!strcmpi(argv[0], "proto")) && (!bStandAlone) && (!flagactiveX))
			{
				if ((cmdline[0] == 0) || (!stricmp (cmdline, "/INSTALL")))
					regproto(argv[1]);
			}
			else if ((n > 1) && (!strcmpi(argv[0], "codec_pkg")))
			{
				regcodec(argv[1]);
			}
			//$BLG - v5.2.06:  (Moved to LoadUsmUserIni())
			/*
			//$ 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;
}


//$BLG - v5.2.06: Add
int LoadUsmUserIni(void)
{
	FILE *f;
	//$BLG - v5.2.06: Modif
	//char src[4096];
	char src[16385];
	char *line;
  char buf[512];
  char* argv[128];
  char path[1024];
  int n;
	time_t timep;
	struct tm *res;
	
	//$BLG - v5.2.06: Add
	TCHAR curpath[MAX_PATH];

	forcedIP[0] = 0;
	HTTPproxy[0] = 0;
	SOCKSsetUsername(NULL);
	SOCKSsetPassword(NULL);
	hardware3d[0] = 0;

  //$BB add stand alone mode
  if (!bStandAlone)
  {
	  //$BLG - v5.2.06: Add
	  if (!SCcheckuserini())
		  MMechostr(0, "Error: UsmUser.ini file not found and not initialiazed\n");
  	
	  strcpy(buf, mydcmtspath2);
	  strcat(buf, "usmuser.ini");
	  f = fopen(buf, "rb");
  }
  else
    f = fopen("usm.ini", "rb");

	if (f == NULL)
	{
		return 0;
	}
	
	src[fread(src, 1, 16384, f)] = 0;
	fclose(f);
	
	b_logsshouldbeset = false;
	
	line = src;
	while (line = stdGetLine(line, buf, 512))
	{
		if (n = strCutting(buf, argv))
		{
			if ((n > 1) && (!strcmpi(argv[0], "port")))
			{
				STDPORT = atoi(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], "log")))
			{
				if ((flog) && (!strcmpi(argv[1], "no")))
				{
					fclose(flog);
					flog = NULL;
					b_logsshouldbeset = false;
				}
				else if ((flog == NULL) && (!strcmpi(argv[1], "yes")))
				{
					//$BLG - v5.2.06: Add
					GetCurrentDirectory(MAX_PATH, curpath);
					strcpy(path, logfilespath2);
					//$BLG - v5.2.06: Del (Already set in logfilespath2)
					//strcat(path, "log/");
					b_scollogsdir = true;
					if (!SetCurrentDirectory(path))
            b_scollogsdir = CreateDirectory(path, NULL);
          //else
          //$BB not else we need to restore current path after test
					SetCurrentDirectory(curpath);
					
					if (b_scollogsdir)
					{
						//$BLG - v5.2.06: Del
            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");
						//$BLG - v5.2.06: Del (No more useful)
						//$BLG - Note: Next line allows log creation under Scol/ if Scol/log/ doesn't exist ... added log/ creation above ...
            //if (!flog) flog = fopen(path+strlen("log/"), "w");
					}
					
					b_logsshouldbeset = true;
				}
			}
			else if ((n > 1) && (!strcmpi(argv[0], "echo")))
			{
				MaskEcho = myhtoi(argv[1]);
			}
			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;
			}
			//$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;
      }
      //$FA - End
      
      else if ((n > 1) && (!strcmpi(argv[0], "forcedIP")) && (strlen(argv[1]) < 64))
			{
				strcpy(forcedIP, argv[1]);
			}
      else if ((n > 1) && (!strcmpi(argv[0], "refreshIP")) && (!strcmpi(argv[1], "no")))
			{
				flagrefreshIP = 0;
			}
			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], "3dhardware")) && (strlen(argv[1]) < 128))
			{
				strcpy(hardware3d, argv[1]);
			}
		}
  }
	return 0;
}


void startscol()
{
  if (fstart) return;
	fstart = 1;
	if (mainscol())
    //$BB change AX method
		//if (!flagactiveX) 
    EndScolMachine(0);
}

static BOOL AnyInstance(HANDLE this_inst, int cmdshow, LPSTR cmdline)
{
	fstart = 0;
  thisinst = this_inst;
	firstScol = SCOL_INSTANCE_NORMAL;
	if (!strcmpi(cmdline, "/autostart"))
	{
		cmdline = "";
    firstScol = SCOL_INSTANCE_AUTOSTART;
	}

  /*
  Here, we detect if this instance is the first instance launched.
  How does it works?
  We create a named mutex, the true parameter indicating that we want to check if this instance created the mutex.
  If it's the first one, then no problems, it's obviously the case.
  If not, the GetLastError return ERROR_ALREADY_EXISTS value.
  TODO: find an alternative for linux. maybe using boost::interprocess::interprocess_mutex and the try_lock() function.

  const char* scolMutexFirstInstance = "Scol first instance";   
  try
  {
    // When "killer" variable goes out of scope, mutex is destroyed.
    struct named_mutex_killer
    {
      ~named_mutex_killer()
      {
        boost::interprocess::named_mutex::remove(scolMutexFirstInstance);
      }
    } killer;
 
    boost::interprocess::named_mutex instance_lock(create_only, scolMutexFirstInstance);
 
    std::cout << "Only instance of application started..." << std::endl;
  }
  catch(boost::interprocess::interprocess_exception &e)
  {
    std::cout << "Running second instance of application" << std::endl;
  }
  */
	CreateMutex(NULL, TRUE, "Scol_first");
  if ((firstScol == SCOL_INSTANCE_NORMAL) && (!GetLastError()))
    firstScol = SCOL_INSTANCE_FIRST;

  //$BB retrieve stand alone mode before getting directories
  GetStandAlone();
  if (FindPaths(cmdline)) return FALSE;

  flog = NULL;
	flaglogwin = 1;
	flaglogwinsup = 0;
	flaglog = 1;
	
  SCiniDLLs();

	McodecInit();
	mt_ini();

	LoadUsmIni(cmdline);

	//$BLG - v5.2.06: Add
  LoadUsmUserIni();
	//$BLG - End

  if (!stricmp (cmdline, "/INSTALL")) return FALSE;

	flaglog = 1;
//	if (flagactiveX) _asm { int 3};

  if (scriptname[0] == 0 && flaglogwinsup)
    Tiniterm(&tcons, scriptname, SW_SHOW);
  else
    Tiniterm(&tcons, scriptname, SW_HIDE);

  if (!tcons.hwnd)
    return FALSE;

  MMechostr(0, "Log File of Scol Virtual Machine\n");
  MMechostr(0, "         Version: %s\n", VERSION_NAME);
  MMechostr(0, "--------------------------------\n");
	MMechostr(0, "\n");
	MMechostr(0, "> Checking useful directories\n");
	MMechostr(0, "Install Dir:      %s\n", execpath2);
  
  //$BB add stand alone mode
  if (!bStandAlone)
  {
    if (SUCCEEDED(hr_lappdatapath))
		  if (b_scollocaldir)
			  MMechostr(0, "Local App Data:   %s\n", lappdatapath2);
		  else
			  MMechostr(0, "Local App Data:   Could not create local Scol root directory\n");
	  else
		  MMechostr(0, "Local App Data: failed\n");
	  if (SUCCEEDED(hr_mydcmtspath))
		  if (b_scoluserdir)
			  MMechostr(0, "User documents:   %s\n", mydcmtspath2);
		  else
			  MMechostr(0, "User documents:   Could not create user Scol root directory\n");
	  else
		  MMechostr(0, "User documents: failed\n");
  }

  if (b_logsshouldbeset)
	  if (b_scollogsdir)
		  MMechostr(0, "Log files:        %s\n", logfilespath2);
	  else
		  MMechostr(0, "Log files:        Could not create Scol log files directory\n");
  else
	  MMechostr(0, "Log files:        not set - OK\n");

  if (SCKinit(tcons.hwnd))
	{ 
		MessageBox(NULL, "Tcp-Ip protocol is not installed\nYou need to install it first","Error",0);
    FILE* f;
    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
  /*
    //$BB need to test the scol process here
  && (countOtherScolProcesses()) == 0
  */
  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
			//$BLG - v5.2.06: Modif
			//I added a parameter to differentiate a Scol.exe launched by clicking on exe
			//from one launched by clicking a .scol file (the case here).
			//The parameter is reseted to "" below when no more needed.
			//if (((int)ShellExecute(NULL,"open",execname,0,execpath2,SW_SHOW))>32)
			if (((int)ShellExecute(NULL, "open", execname, "/FROMSCRIPT", execpath2, SW_SHOW))>32)
      {
        //wait for the main scol port activation
        int waitTime = 500; //wait in millisecond
        int nbRetry = 60; //timeout of 30 seconds
        int retry = 0;
        while ((retry < nbRetry) && ((TrySUP() == 0)))
        {
				  Sleep(waitTime);
          retry++;
        }
      }
	    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, bWM_SCOLEND, 0, 0);
	}
#endif

    SCOLInit();
    SetTimer(tcons.hwnd, 1, 1000, NULL);

    //$BB init the ax message window
    if (flagactiveX)
    {
      COPYDATASTRUCT cpd;
      cpd.dwData = WM_SCOLSETWPTR;
      cpd.cbData = sizeof(tcons.hwnd);
      cpd.lpData = (PVOID)&tcons.hwnd;
      
      SendMessage(ActiveXhwnd,WM_COPYDATA,(WPARAM)hscol,(LPARAM)(LPVOID)&cpd);
    }
    return(TRUE);
}

/*!
Register two windows classes schemes that will be used in subsequent calls to CreateWindow (in lib2D)
*/
static BOOL RegisterWindowSchemeClasses(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);
}


extern "C" __declspec (dllexport) int SCOLWinMain(HINSTANCE this_inst, LPSTR cmdline, int cmdshow, int size)
{
  MSG        msg;
  extern int WM_TMM;

	//$BLG - v5.2.06: Add
	if (!strcmp(cmdline, "/FROMSCRIPT"))
	{
		cmdline[0] = 0;
		startmode = 1;
	}
	else
		startmode = 0;

	CBinit = NULL;
  LocalMessage = NULL;
  ScolMemoryLength = size;
  flagactiveX = 0;
  
  RegisterWindowSchemeClasses(this_inst);
  if (!AnyInstance(this_inst, cmdshow, cmdline))
    return (FALSE);

  while (GetMessage(&msg, NULL, 0, 0))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return( msg.wParam );
}


extern "C" __declspec (dllexport) int SCOLWinMainActiveX(HINSTANCE this_inst, LPSTR cmdline, int cmdshow, int (*cbinit)(mmachine m), int size, HWND axhwnd, int (*cbmes)(char * buf))
{
    char MyPath [1024];
    long msize;
    int i;

	  //$BLG - v5.2.06: Add
	  startmode = 0;
	
    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);
    
    sprintf(execname, "%s", (MyPath+1));
    i = 0;
    while (((i <= msize) && (execname[i]!='\"'))) i++;
    execname[i] = 0;

    i = msize;
    while (i && (MyPath[i]!='\\') && (MyPath[i]!='/')) i--;

    if ((MyPath[i] == '\\') || (MyPath[i] == '/')) 
    {
      MyPath[i+1] = 0;
      if (MyPath[0] == '"') 
        sprintf(MyPath, "%s", MyPath+1);

      SetCurrentDirectory(MyPath);
    }

    RegisterWindowSchemeClasses(this_inst);
    if (!AnyInstance(this_inst, cmdshow, cmdline)) 
    {
      MessageBox(NULL, "Cannot open the ActiveX", "ERROR", 0);
      return(FALSE);
    }
   
   return (VERSION_N);
}


/* 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;
}