/***********************************************************/
/*                                                         */
/* main.cpp                                                */
/*                                                         */
/* usmwin project                                          */
/*                                                         */
/* scol v 4 : modified by Loïc Berthelot,                  */
/*                        CryoNetworks, june 2001 :        */
/*  - the ActiveX registration is now done by usmwin       */
/*    (previously done by scol installer)                  */
/*  - in order to make it work :                           */
/*       + an "activex" keyword has been added in the      */
/*         "usm.ini" file. It points the name of           */
/*         scol-activex dll that must be used.             */
/*       + a "_GetDllVersion" function has been added to   */
/*         the scol-activex dll, in order to get the dll   */
/*         version number.                                 */
/*                                                         */
/***********************************************************/

#include<windows.h>
#include<stdio.h>
#include<direct.h>

//$BLG - v5.2.06: Add
#include<shlobj.h>
#include<string>

/************************************************************/
/* scol v 4                                                 */
/*                                                          */
/* internal error codes for ActiveX registration management */
/*                                                          */
/************************************************************/

#define SCOLACTIVEX_REG_SUCCESS       0x00000000    // registration OK
#define SCOLACTIVEX_REG_UNAUTHORIZED  0x00000001    // user is not authorized to register
#define SCOLACTIVEX_REG_ERROR         0x00000002    // wheeuurk : dll not found, registration function pointer not found...

//Scol Class ID (ActiveX component ID, in registry)
//#define SCOL_CLSID                    "CLSID\\7A96FF35-4937-11D1-8F2C-00609779BDA3\\Version"

// ActiveX registration function decl
typedef BOOL (WINAPI* GETDLLVERSION) (LPSTR);
static GETDLLVERSION p_GetDllVersion;

typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);

LPFN_ISWOW64PROCESS fnIsWow64Process;
BOOL IsWow64()
{
    BOOL bIsWow64 = FALSE;

    //IsWow64Process is not available on all supported versions of Windows.
    //Use GetModuleHandle to get a handle to the DLL that contains the function
    //and GetProcAddress to get a pointer to the function if available.

    fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
        GetModuleHandle(TEXT("kernel32")),"IsWow64Process");

    if(NULL != fnIsWow64Process)
    {
        if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
        {
            //handle error
        }
    }
    return bIsWow64;
}

BOOL IsUserAdmin(HANDLE hToken)
{
    HANDLE hAccessToken;
    UCHAR InfoBuffer[4096]; 
    PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS)InfoBuffer;
    DWORD dwInfoBufferSize;
    PSID psidAdministrators;
    SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
    UINT x;
    BOOL bSuccess;


    if (hToken)
        hAccessToken = hToken;
    else
        if(!OpenProcessToken(GetCurrentProcess(),TOKEN_READ,&hAccessToken))
            //        return(FALSE);
            return(TRUE);

    bSuccess =GetTokenInformation(hAccessToken,TokenGroups,InfoBuffer,
        sizeof(InfoBuffer), &dwInfoBufferSize);

    CloseHandle(hAccessToken);

    if( !bSuccess )
        //        return FALSE;
        return(TRUE);

    if(!AllocateAndInitializeSid(&siaNtAuthority, 2,
        SECURITY_BUILTIN_DOMAIN_RID,
        DOMAIN_ALIAS_RID_ADMINS,
        0, 0, 0, 0, 0, 0,
        &psidAdministrators))
        //    return FALSE;
        return(TRUE);

    // assume that we don't find the admin SID.
    bSuccess = FALSE;

    for(x=0;x<ptgGroups->GroupCount;x++)
    {
        if(EqualSid(psidAdministrators, ptgGroups->Groups[x].Sid) )
        {
            bSuccess = TRUE;
            break;
        }
    }
    FreeSid(psidAdministrators);
    return bSuccess;
}

/*****************************************************************/
/* scol v 4                                                      */
/*                                                               */
/* BOOL CheckActiveXVersion (LPCSTR, LPCSTR)                     */
/*                                                               */
/* returns 0 if the version of scol-activex dll which is pointed */
/* by usm.ini is different from the one which is registered in   */
/* the Windows registry.                                         */
/* returns non-zero if they're the same.                         */
/*                                                               */
/*****************************************************************/
/*
BOOL CheckActiveXVersion (LPCSTR DllName, LPCSTR DllPathName)
{
	TCHAR axVer [256];
	TCHAR regAxVer [256];
	DWORD type, size;
	HINSTANCE axDll;
	HKEY scolKey;

  //first, get the version number from the dll pointed by usm.ini
	if ((axDll = LoadLibrary (DllName)) == NULL)
		return 0;	

	p_GetDllVersion = (GETDLLVERSION) GetProcAddress (axDll, "_GetDllVersion");

	if (!p_GetDllVersion)
	{
		FreeLibrary (axDll);
		return 0;
	}

	if (!p_GetDllVersion (axVer))
	{
		FreeLibrary (axDll);
		return 0;
	}


	//then, get the one from the registry
	if (RegOpenKeyEx (HKEY_CLASSES_ROOT, SCOL_CLSID, 0, KEY_READ, &scolKey) != ERROR_SUCCESS) 
	{
		FreeLibrary (axDll);
  		return 0;
	}

	type = REG_SZ;
	size = sizeof (regAxVer);
	if (RegQueryValueEx (scolKey, NULL, NULL, &type, (LPBYTE)regAxVer, &size) != ERROR_SUCCESS)
	{
		RegCloseKey (scolKey);
		FreeLibrary (axDll);
		return 0;
	}

	//if they're different, returns 0
	if (_strnicmp (axVer, regAxVer, strlen (axVer)))
	{
		RegCloseKey (scolKey);
    	FreeLibrary (axDll);
		return 0;
	}

	RegCloseKey (scolKey);
   	FreeLibrary (axDll);

	return 1;
}
*/

/*****************************************************************/
/* scol v 4                                                      */
/*                                                               */
/* DWORD RegisterActiveX (LPCSTR)                                */
/*                                                               */
/* make the scol-activeX component register.                     */
/* returns SCOLACTIVEX_REG_SUCCESS if sucess.                    */
/* returns an error code if fails.                               */
/*                                                               */
/*****************************************************************/
DWORD RegisterActiveX (LPCSTR DllName)
{
  FARPROC lpDllEntryPoint;
  
  HINSTANCE hLib;


  hLib=LoadLibrary(DllName);

  if (!hLib)
  {
		//Error (getvar("ERROR_LOAD_DLL"),DllName);
	  	return SCOLACTIVEX_REG_ERROR;
  }
	
  lpDllEntryPoint=GetProcAddress(hLib,"DllRegisterServer");

  if (lpDllEntryPoint == NULL)
  {
		//Error(getvar("ERROR_REG_DLL"),DllName);
		FreeLibrary(hLib);
		return SCOLACTIVEX_REG_ERROR;
  }
     
  else if (((*lpDllEntryPoint)()) != S_OK)
  {
		FreeLibrary(hLib);
		return SCOLACTIVEX_REG_UNAUTHORIZED;
  };

  FreeLibrary(hLib);

  return SCOLACTIVEX_REG_SUCCESS;
}


/* récupère la première ligne
retourne un pointeur vers la ligne suivante ou NULL si terminé ou erreur*/
char *stdGetLine(char *src,char *buf,int n)
{
  int c,i;

  while((c=(*(src++)))<32) if (c==0) return NULL;
  i=0;
  buf[i++]=c;
  while(((c=(*(src++)))>=32)&&(c)&&(i<n)) buf[i++]=c;
  if (c==0) src--;
  if (i==n) return NULL;
  buf[i]=0;
  return src;
}


/* decoupage d'une chaine en mots (retourne le nombre de mots)
 format strbuild */
int strCutting(char *comm, char **argv)
{
  int i,j,k,argc;
  
  i=0;
  j=-1;
  argc=0;

  while(comm[i])
  {
	  if (comm[i]==32)
	  {
		  if (j>=0) comm[j]=0;
		  j=-1;
		  i++;
	  }
	  else
	  {
		  if (j==-1)
		  {
			  j=i;
			  argv[argc++]=&comm[i];
		  }
		  if (comm[i]=='\\')
		  {
			  i++;
              if ((comm[i]>='0')&&(comm[i]<='9'))
			  {
				  k=comm[i]-'0';
				  i++;
				  if ((comm[i]>='0')&&(comm[i]<='9'))
				  {
					  k=k*10+comm[i]-'0';
					  i++;
					  if ((comm[i]>='0')&&(comm[i]<='9'))
					  {
						  k=k*10+comm[i]-'0';
						  i++;
					  }
				  }
				  comm[j++]=k;
			  }
			  else if (comm[i]=='n')
			  {
				  comm[j++]=10;
				  i++;
			  }
			  else if (comm[i]=='z')
			  {
				  comm[j++]=0;
				  i++;
			  }
			  else
			  {
				  comm[j++]=comm[i];
				  if (comm[i]) i++;
			  }
		  }
		  else comm[j++]=comm[i++];
	  }
  }
  if (j>=0) comm[j]=0;
  return argc;
}


typedef int (*FCM)(HANDLE this_inst, LPSTR cmdline, int cmdshow,int size);


//$BLG - v5.2.06: Modif
//char srcbuf[16384];
char srcbuf[16385];


//$BLG - v5.2.06: Add
//char execpath[1024];					// Path to scol.exe: path
//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/
//HRESULT hr_cappdatapath;


void RegisterMozillaPlugin(char* mzName, char* protoName)
{
  HKEY hkey;
  std::string regsuffix(protoName);
  std::string tmpstr;
  std::string regBase = IsWow64() ? std::string("SOFTWARE\\Wow6432Node") : std::string("SOFTWARE");

  tmpstr = regBase + std::string("\\MozillaPlugins\\@scolring.org/") + regsuffix;
  RegCreateKey(HKEY_LOCAL_MACHINE, tmpstr.c_str(), &hkey);

  tmpstr = regsuffix + std::string(" Plugin For Mozilla Based Broswer");
  RegSetValueEx (hkey, "Description", 0, REG_SZ, (LPBYTE)tmpstr.c_str(), tmpstr.length());
  RegSetValueEx (hkey, "Path", 0, REG_SZ, (LPBYTE)mzName, strlen(mzName));
  tmpstr = regsuffix + std::string(" Plugin");
  RegSetValueEx (hkey, "ProductName", 0, REG_SZ, (LPBYTE)tmpstr.c_str(), tmpstr.length());
  RegSetValueEx (hkey, "Vendor", 0, REG_SZ, (LPBYTE)"Scolring", 9);
  RegSetValueEx (hkey, "Version", 0, REG_SZ, (LPBYTE)"1.0.0.0", 8);
  RegCloseKey(hkey);
  
  tmpstr = regBase + std::string("\\MozillaPlugins\\@scolring.org/") + regsuffix + std::string("\\MimeTypes\\application/x-") + regsuffix;
  RegCreateKey(HKEY_LOCAL_MACHINE, tmpstr.c_str(), &hkey);
  tmpstr = regsuffix + std::string(" Plugin For Mozilla Based Broswer");
  RegSetValueEx (hkey, "Description", 0, REG_SZ, (LPBYTE)tmpstr.c_str(), tmpstr.length());
  RegSetValueEx (hkey, "Suffixes", 0, REG_SZ, (LPBYTE)regsuffix.c_str(), regsuffix.length());
  RegCloseKey(hkey);
  
  tmpstr = regBase + std::string("\\MozillaPlugins\\@scolring.org/") + regsuffix + std::string("\\Suffixes");
  RegCreateKey(HKEY_LOCAL_MACHINE, tmpstr.c_str(), &hkey);
  tmpstr = regsuffix + std::string(" script");
  RegSetValueEx (hkey, regsuffix.c_str(), 0, REG_SZ, (LPBYTE)tmpstr.c_str(), tmpstr.length());
  RegCloseKey(hkey);
}


int LoadUsmIni(HINSTANCE this_inst, LPSTR cmdline,int cmdshow)
{
	FILE *f;
	char *line;
  char buf[512];
  char* argv[128];
  TCHAR mzName [MAX_PATH];
	TCHAR axName [MAX_PATH];
  TCHAR dllName [MAX_PATH];
  TCHAR protoName [512];
  DWORD axRegCode;
  int n;
  HMODULE hLibrary;
  FCM SCOLloadDLL;
  
  memset(mzName, 0, MAX_PATH);
  memset(axName, 0, MAX_PATH);
  memset(dllName, 0, MAX_PATH);
  memset(protoName, 0, 512);

  //$BLG - v5.2.06: Add
  //char *ptr;

	//$BLG - v5.2.06: Modif (Sources from Kernel45/myloop.cpp)
	/*
	if (f=fopen("usm.ini","rb"))
	*/
	//$BLG - v5.2.06: Modif2 (Moving usm.ini back to install directory)
	/*
	// execpath
	GetCurrentDirectory (512, execpath);
	if ((execpath[strlen(execpath)-1] == '\\') || (execpath[strlen(execpath)-1] == '/'))
		execpath[strlen(execpath)-1] = 0;
	//execsubdir
	ptr = strrchr(execpath, '\\');
	if (ptr == NULL)
		ptr = strrchr(execpath, '/');
	if (ptr == NULL)
		execsubdir[0] = 0;
	else
		strncpy_s(execsubdir, ptr+1, strlen(execpath)+execpath-ptr);
	//cappdatapath & cappdatapath2
	cappdatapath[MAX_PATH-1] = 0;
	cappdatapath2[0] = 0;
	hr_cappdatapath = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, cappdatapath);
	if (SUCCEEDED(hr_cappdatapath))
	{
		strcat_s(cappdatapath, "/");
		strcat_s(cappdatapath, execsubdir);
		strcpy_s(cappdatapath2, cappdatapath);
		strcat_s(cappdatapath2, "/");
		//$BLG - Note: Scol root directory in Common App Data is created during Voyager install
	}
	//usm.ini file path
	strcpy_s(buf, cappdatapath2);
	strcat_s(buf, "usm.ini");
	if (!fopen_s(&f, buf, "rb"))
	*/
	if (!fopen_s(&f, "usm.ini", "rb"))
	{
		//$BLG - v5.2.06: Modif
		//srcbuf[fread(srcbuf,1,2047,f)]=0;
		srcbuf[fread(srcbuf, 1, 16384, f)]=0;
		
		fclose(f);
		
		line=srcbuf;
		while(line=stdGetLine(line,buf,512))
		{
			if (n=strCutting(buf,argv))
			{
				//register ActiveX
				if (((cmdline == NULL) || (!strcmp (cmdline, "") || (!_strnicmp (cmdline, "/install", strlen ("/install"))))) && (n>1))
				{
          if (!_strnicmp (argv[0], "activex", strlen("activex")))
          {
					  DWORD i;
  	
					  GetModuleFileName(NULL, axName, 512);
					  i = (DWORD) (strlen ((char*)axName) - 1);
					  while ((axName[i] != '/') && (axName[i] != '\\'))
						  i--;
					  axName[i+1] = '\0';

					  strcat_s(axName, argv[1]);
  	
            i = 0;
					  while (i < strlen(axName))
            {
              if (axName[i] == '/')
                axName[i] = '\\';
              i ++;
            }
          }
          else if (!_strnicmp (argv[0], "mozplugin", strlen("mozplugin")))
          {
            DWORD i;
            
					  GetModuleFileName(NULL, mzName, 512);
					  i = (DWORD) (strlen ((char*)mzName) - 1);
					  while ((mzName[i] != '/') && (mzName[i] != '\\'))
						  i--;
					  mzName[i+1] = '\0';
            
					  strcat_s(mzName, argv[1]);

            i = 0;
					  while (i < strlen(mzName))
            {
              if (mzName[i] == '/')
                mzName[i] = '\\';
              i ++;
            }
          }
          else if (!_strnicmp (argv[0], "proto", strlen("proto")))
          {
            strcpy_s(protoName, argv[1]);
          }
        }

        if ((n>1) && (!_strcmpi(argv[0],"scol")))
        {
          strcpy_s(dllName, argv[1]);
        }
			}
		}
	}

  if (dllName[0] != 0)
  {
    //register ax
    //test if user as the admin rights to register the AX
    if (IsUserAdmin(0))
    {
      if (axName[0] != 0)
      {
        axRegCode = RegisterActiveX (axName);
        
        if (axRegCode == SCOLACTIVEX_REG_ERROR)
        {
	        MessageBox (NULL, "AxScoll.dll error", "Scol Error", MB_OK);
	        return -1;
        }
        
        //$BB remove check version and error dialog since windows 7 do not have admin access on default
        /*
        if (axRegCode == SCOLACTIVEX_REG_UNAUTHORIZED)
        {
	        if (!CheckActiveXVersion (argv[1], axName))
	        {
		        TCHAR msg[512];
		        sprintf_s(msg, "%s\n%s\n%s", "You don't have the required access to register Scol as an ActiveX component.", 
									        "Some Scol functionnality will not be available.",
									        "Contact your administrator to register ActiveX library with Scol.");		
		        MessageBox (NULL, msg, "Scol ActiveX Warning", 0);
	        }
        }
        */
      }
    }

    //register mozilla plugin
    if((mzName[0] != 0 ) && (protoName[0] != 0))
      RegisterMozillaPlugin(mzName, protoName);
		
		//launch scol machine 
	  hLibrary=LoadLibrary(dllName);
		if (hLibrary)
		{
			SCOLloadDLL=(FCM)GetProcAddress(hLibrary,"SCOLWinMain");
			if (SCOLloadDLL)
			{
				return SCOLloadDLL(this_inst, cmdline, cmdshow, 1024*1024);
			}
		}
  }
  else
  {
  	MessageBox(NULL,"Bad Installation","Scol Error",MB_OK);
	}
	return 0;
}


int PASCAL WinMain(HINSTANCE this_inst, HINSTANCE prev_inst, LPSTR cmdline, int cmdshow)
{
  // prev_inst is allways null in Windows 32bit, this is a reminiscent code of win16!
	int i,j;
	char buf[1024];
    
	buf[0]=0;
	GetModuleFileName(NULL,buf,1024);
	i=0;j=-1;
	
	while(buf[i])
	{
		if ((buf[i]=='/')||(buf[i]=='\\')) j=i+1;
		i++;
	}
	
	if (j>0)
	{
		buf[j]=0;
		SetCurrentDirectory(buf);
	}

	return LoadUsmIni(this_inst, cmdline,cmdshow);
}