/**********************************************/
/*                                            */    
/* iprocess.cpp                               */
/*                                            */
/* allows installer to check scol processes   */
/* and to kill them                           */
/*                                            */
/* scol v 4                                   */
/*                                            */
/* by Loïc Berthelot, CryoNetworks, may 2001  */
/*    Josselin Dumay, CryoNetworks, mars 2001 */
/*                                            */
/**********************************************/


//$LB (20/03/2005) : change usmwin.exe to scol.exe




#include <stdio.h>

#include <windows.h>
#include <string.h>
#include "iWinVersion.h"





/************************************************************************************************/
/**                                                                                            **/
/** INTERNAL BODY WIN NT4                                                                      **/
/**                                                                                            **/
/**   static BOOL InitPSAPI()                                                                  **/
/**   static BOOL ClosePSAPI()                                                                 **/
/**   DWORD NTGetModuleBaseName(HANDLE hProcess,HMODULE hModule,LPTSTR lpBaseName,DWORD nSize) **/
/**   BOOL NTIsScolProcess (DWORD pid)                                                         **/
/**   BOOL NTIsScolRunning ()                                                                  **/
/**                                                                                            **/
/**                                                                                            **/
/** INTERNAL BODY WIN 95 / 98 / ME / 2000                                                      **/
/**                                                                                            **/
/**   static BOOL InitTOOLHELP32()                                                             **/
/**   static BOOL CloseTOOLHELP32()                                                            **/
/**   BOOL OSGetProcessModule (DWORD dwPID)                                                    **/
/**   BOOL OSIsScolRunning ()                                                                  **/ 
/**                                                                                            **/
/**                                                                                            **/
/** EXTERNAL BODY                                                                              **/
/**                                                                                            **/
/**   BOOL KillScol ()                                                                         **/
/**   BOOL IsScolRunning ()                                                                    **/
/**                                                                                            **/
/************************************************************************************************/




//$LB (20/03/2005) : change usmwin.exe to scol.exe
#define USMWIN_MODULE_NAME1 "USMWIN.EXE"
#define USMWIN_MODULE_NAME2 "SCOL.EXE"
#define USMWIN_MODULE_SIZENAME1 10
#define USMWIN_MODULE_SIZENAME2 8


DWORD *scolPIDs = NULL;
DWORD   scolPIDsSize = 0;










/***********************************************************************************/
/***********************************************************************************/
/**                                                                               **/
/**     I N T E R N A L        B O D Y         WIN NT4                            **/
/**                                                                               **/
/***********************************************************************************/
/***********************************************************************************/

static BOOL bPSAPIInitialized					= FALSE;

//WinNT Functions, via PSAPI DLL
typedef BOOL (WINAPI *ENUMPROCESSES)      (DWORD *, DWORD, DWORD *);
typedef BOOL (WINAPI *ENUMPROCESSMODULES) (HANDLE, HMODULE *, DWORD, LPDWORD);
typedef DWORD (WINAPI *GETMODULEBASENAME) (HANDLE, HMODULE, LPTSTR, DWORD);

static ENUMPROCESSES      p_EnumProcesses       = NULL;
static ENUMPROCESSMODULES p_EnumProcessModules  = NULL;
static GETMODULEBASENAME  p_GetModuleBaseName	= NULL;

HINSTANCE hPSAPI                                = NULL;





/****************************************/
/* static BOOL InitPSAPI()              */
/*                                      */
/* PSAPI initialization                 */
/****************************************/   
static BOOL InitPSAPI()
{
    if ( bPSAPIInitialized )
        return ( TRUE ) ;

BOOL bRet = FALSE;
    
    // loading PSAPI dll
    HINSTANCE hPSAPI = LoadLibrary ( "PSAPI.DLL" ) ;

    if (hPSAPI != NULL)
	{
	    // get functions pointers
		p_EnumProcesses =
			(ENUMPROCESSES)GetProcAddress (hPSAPI,
						  				  "EnumProcesses" );
		p_EnumProcessModules =
           (ENUMPROCESSMODULES)GetProcAddress ( hPSAPI ,
                                                "EnumProcessModules" ) ;
		p_GetModuleBaseName =
			(GETMODULEBASENAME)GetProcAddress ( hPSAPI ,
                                            "GetModuleBaseNameA" ) ;
		bRet =	p_EnumProcesses &&
				p_EnumProcessModules &&
				p_GetModuleBaseName;
	}
	else bRet = FALSE;

	if (bRet)
		bPSAPIInitialized = TRUE ;

    return ( TRUE ) ;
}






/****************************************/
/* static BOOL ClosePSAPI()             */
/*                                      */
/* close the PSAPI library              */
/****************************************/  
static BOOL ClosePSAPI()
{
	if (hPSAPI)
	{
		FreeLibrary (hPSAPI);
		hPSAPI = NULL;
	}
	bPSAPIInitialized = FALSE;
	return (TRUE);
}















/***********************************************/
/* DWORD NTGetModuleBaseName                   */
/*           (HANDLE hProcess,HMODULE hModule, */
/*           LPTSTR lpBaseName,DWORD nSize)    */
/*                                             */
/* ==> IGetModuleBaseName                      */
/***********************************************/   
DWORD NTGetModuleBaseName(HANDLE hProcess,HMODULE hModule,LPTSTR lpBaseName,DWORD nSize)
{
    // initialisation de PSAPI.DLL si necessaire
    if (!InitPSAPI())
	{
		ClosePSAPI();
        return 0;
	}
    
	return p_GetModuleBaseName( hProcess,hModule,lpBaseName,nSize);
}




#define DEFSIZE 10
/***************************************/
/* BOOL NTIsScolProcess                */
/*                                     */
/* return TRUE if the pid is the pid   */
/* of a UsmWin Process.                */
/***************************************/
BOOL NTIsScolProcess (DWORD pid)
{

   // initialisation de PSAPI.DLL si necessaire
    if (!InitPSAPI())
	{
		ClosePSAPI();
        return FALSE;
	}


HANDLE  hProc;
DWORD   defsize;
HMODULE *pMods = NULL;
DWORD   pModsSize;
DWORD   dwTotal = 0;
TCHAR   lpBaseName[USMWIN_MODULE_SIZENAME1+1];


	_log("NTIsScolProcess entry : PID=%d\n", pid);

    // process ID --> process handle
    hProc = OpenProcess ( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, pid);
    if (hProc==NULL)
	{
		_log("NTIsScolProcess end (OpenProcess)\n");
        return FALSE;
	}


	// check if function pointer is still good
	if (IsBadCodePtr ( (FARPROC)p_EnumProcessModules ))
    {
		CloseHandle(hProc);
		_log("NTIsScolProcess end (BadCodePtr)\n");
        return FALSE;
    }



	// modules list
	defsize	  = DEFSIZE*sizeof(HMODULE);
    pMods=(HMODULE *)malloc(defsize);

	_log("before p_EnumProcessModules\n");
	if (!p_EnumProcessModules (hProc,pMods,defsize,&dwTotal))
	{
		CloseHandle(hProc);
		free(pMods);
		_log("NTIsScolProcess end (p_EnumProcessModules)\n");
		return FALSE;
	}


	//if the allocated size is not enough, do it again
	if (dwTotal > defsize)
	{
	  // on réalloue la bonne taille pour le buffer des modules
	  pMods=(HMODULE *)realloc(pMods,dwTotal);
	
	  // si la taille du buffer etait trop petit => on redemande la liste
	  if (!p_EnumProcessModules (hProc,pMods,dwTotal,&dwTotal))
	  {	
		CloseHandle(hProc);
		free(pMods);
		_log("NTIsScolProcess end (p_EnumProcessModules2)\n");
        return FALSE;
	  }
	}

	// nb of modules
	pModsSize = dwTotal/sizeof(HMODULE);
	_log("pModsSize=%d\n", pModsSize);

	for (DWORD i=0; i < pModsSize; i++)
	{
		NTGetModuleBaseName (hProc, pMods[i], lpBaseName, USMWIN_MODULE_SIZENAME1+1);
		if (lpBaseName)
			_log("module=<%s>\n", lpBaseName);
		else
			_log("module=NULL\n");



//$LB (20/03/2005) : change usmwin.exe to scol.exe
 	    if  (
			  (strnicmp (lpBaseName, USMWIN_MODULE_NAME1, USMWIN_MODULE_SIZENAME1) == 0)
			|| 
			  (strnicmp (lpBaseName, USMWIN_MODULE_NAME2, USMWIN_MODULE_SIZENAME2) == 0)
			)
		{
			CloseHandle(hProc);
			free(pMods);
			_log("NTIsScolProcess end : found=TRUE\n");
			return TRUE;
		}
	}

    CloseHandle(hProc);
	free(pMods);
	_log("NTIsScolProcess end : found=FALSE\n");
	return FALSE;
}





/***************************************/
/* BOOL NTIsScolRunning                */
/*                                     */
/* IsScolRunning for Windows NT4       */
/***************************************/
BOOL NTIsScolRunning ()
{
DWORD *lpdwPIDs = NULL;
DWORD dwPIDsSize = 256*sizeof(DWORD);
DWORD pidsCount;
DWORD dwPIDsReturnedSize = 0;


	_log("NTIsScolRunning entry\n");

   if (!InitPSAPI())
   {
	   ClosePSAPI();
		_log("NTIsScolRunning end (InitPSAPI)\n");
	   return FALSE;
   }


   // repeat operations until given
   // size is sufficient
   do
   {
	   if (lpdwPIDs)
	   {
	     free (lpdwPIDs);
		 lpdwPIDs = NULL;
	     dwPIDsSize *= 2;
	   }

	   lpdwPIDs = (DWORD*)malloc (dwPIDsSize);

	   if (!p_EnumProcesses (lpdwPIDs, dwPIDsSize, &dwPIDsReturnedSize))
	   {
			ClosePSAPI();
			_log("NTIsScolRunning end (p_EnumProcesses)\n");
			return FALSE;
	   }
   }
   while (dwPIDsReturnedSize == dwPIDsSize);

   pidsCount = dwPIDsReturnedSize/sizeof(DWORD);
   _log("pidsCount=%d\n", pidsCount);
   for (DWORD i=0; i < pidsCount; i++)
   {
		if (NTIsScolProcess (lpdwPIDs[i]))
		{
			scolPIDsSize++;
			scolPIDs = (DWORD *)realloc(scolPIDs, sizeof(DWORD)*(scolPIDsSize));
			scolPIDs[scolPIDsSize-1] = lpdwPIDs[i];
		}
   }


   if (lpdwPIDs)
   {
		free (lpdwPIDs);
		lpdwPIDs = NULL;
   }
   ClosePSAPI();

	_log("NTIsScolRunning end : scolPIDsSize=%d\n", scolPIDsSize);
   if (scolPIDsSize == 0)
	   return FALSE;

   return TRUE;
}
















/***********************************************************************************/
/***********************************************************************************/
/**                                                                               **/
/**     I N T E R N A L        B O D Y         WIN 95 / 98 / ME / 2000            **/
/**                                                                               **/
/***********************************************************************************/
/***********************************************************************************/







#include <Tlhelp32.h>

static BOOL           bTHPInitialized           = FALSE ;

/* types for toolhelp32 dynamic function                */
typedef BOOL (WINAPI *MODULEWALK) (HANDLE,LPMODULEENTRY32);
typedef BOOL (WINAPI *THREADWALK) (HANDLE,LPTHREADENTRY32);
typedef BOOL (WINAPI *PROCESSWALK)(HANDLE,LPPROCESSENTRY32);
typedef HANDLE (WINAPI *CREATESNAPSHOT) (DWORD,DWORD);

/* pointers to toolhelp32 dynamic function              */
static CREATESNAPSHOT p_CreateToolhelp32Snapshot = NULL  ;
static MODULEWALK     p_Module32First            = NULL  ;
static MODULEWALK     p_Module32Next             = NULL  ;
static PROCESSWALK    p_Process32First           = NULL  ;
static PROCESSWALK    p_Process32Next            = NULL  ;

HINSTANCE hKernel                                = NULL  ;





/****************************************/
/* static BOOL InitTOOLHELP32()         */
/*                                      */
/* ToolHelp32 initialization            */
/****************************************/   
static BOOL InitTOOLHELP32()
{
    if (bTHPInitialized)
        return ( TRUE ) ;


BOOL bRet = FALSE ;

  

    hKernel = GetModuleHandleA ( "KERNEL32.DLL" ) ;
    
	if (hKernel!=NULL)
    {
        p_CreateToolhelp32Snapshot =
           (CREATESNAPSHOT)GetProcAddress ( hKernel ,
                                            "CreateToolhelp32Snapshot");
        
		p_Module32First = (MODULEWALK)GetProcAddress (hKernel ,
                                                       "Module32First");
        
		p_Module32Next = (MODULEWALK)GetProcAddress (hKernel        ,
                                                      "Module32Next"  );
        p_Process32First =
                (PROCESSWALK)GetProcAddress ( hKernel          ,
                                              "Process32First"  ) ;
        p_Process32Next =
                (PROCESSWALK)GetProcAddress ( hKernel         ,
                                              "Process32Next" ) ;
        

        bRet =  p_Module32First            &&
                p_Module32Next             &&
                p_Process32First           &&
                p_Process32Next            &&
                p_CreateToolhelp32Snapshot    ;
    }
    else
        bRet = FALSE ;

    if (bRet)
        bTHPInitialized = TRUE ;
    return ( bRet ) ;
}






/****************************************/
/* static BOOL CloseTOOLHELP32()        */
/*                                      */
/* close the kernel32 library           */
/****************************************/  
static BOOL CloseTOOLHELP32()
{

	if (hKernel)
	{
		FreeLibrary (hKernel);
		hKernel = NULL;
	}
	bTHPInitialized = FALSE;
	return (TRUE);
}







/*****************************************/
/* BOOL OSGetProcessModule               */
/*                                       */
/* Search scol in modules of a process   */
/* for all Windows but NT4               */
/*****************************************/
BOOL OSGetProcessModule (DWORD dwPID)
{ 
BOOL          bRet        = FALSE; 
BOOL          bFound      = FALSE; 
HANDLE        hModuleSnap = NULL; 
MODULEENTRY32 me32        = {0}; 

 
	_log("OSGetProcessModule entry : PID=%d\n", dwPID);

    // Take a snapshot of all modules in the specified process. 
	_log("before p_CreateToolhelp32Snapshot TH32CS_SNAPMODULE\n");
    hModuleSnap = p_CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); 
    if (hModuleSnap == INVALID_HANDLE_VALUE) {
		_log("OSGetProcessModule end (INVALID_HANDLE_VALUE)\n");
        return (FALSE);
	}
 
    // Fill the size of the structure before using it. 
	memset (&me32, NULL, sizeof (MODULEENTRY32));
    me32.dwSize = sizeof(MODULEENTRY32); 
 
    // Walk the module list of the process, and find the module of 
    // interest.
	_log("before p_Module32First\n");
    if (p_Module32First(hModuleSnap, &me32)) 
    { 
        do 
        {
			if (me32.szModule)
				_log("module=<%s>\n", me32.szModule);
			else
				_log("module=NULL\n");
			

//$LB (20/03/2005) : change usmwin.exe to scol.exe
		   if (
			   (strnicmp (me32.szModule, USMWIN_MODULE_NAME1, USMWIN_MODULE_SIZENAME1) == 0)
			   ||
			   (strnicmp (me32.szModule, USMWIN_MODULE_NAME2, USMWIN_MODULE_SIZENAME2) == 0)
			   )

                bFound =  TRUE;
        }
        while (!bFound && p_Module32Next(hModuleSnap, &me32)); 
 
        bRet = bFound;
    } 
    else 
        bRet = FALSE;           // could not walk module list 
 
    // Do not forget to clean up the snapshot object. 

    CloseHandle (hModuleSnap); 
	_log("OSGetProcessModule end : found=%d\n", bRet);
     return (bRet); 
} 








/*****************************************/
/* OSIsScolRunning                       */
/*                                       */
/* IsScolRunning for all Windows but NT4 */
/*****************************************/
BOOL OSIsScolRunning ()
{
	_log("OSIsScolRunning entry\n");

    if (!InitTOOLHELP32())
	{
		CloseTOOLHELP32();
		_log("OSIsScolRunning end (InitTOOLHELP32)\n");
        return NULL;
	}

	

HANDLE         hProcSnap = NULL ;
PROCESSENTRY32 stPE32;

 
    //  Take a snapshot of all processes in the system. 
	_log("before p_CreateToolhelp32Snapshot TH32CS_SNAPPROCESS\n");
    hProcSnap = p_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 

   if ( hProcSnap==INVALID_HANDLE_VALUE )
	{
		CloseTOOLHELP32();
		_log("OSIsScolRunning end (INVALID_HANDLE_VALUE)\n");
        return FALSE;
	}

    //  Fill in the size of the structure before using it. 
   	memset ( &stPE32 , NULL , sizeof ( PROCESSENTRY32 ) ) ;
    stPE32.dwSize = sizeof ( PROCESSENTRY32 ) ;
   
 
    //  Walk the snapshot of the processes, and for each process, 
    //  take the main module and compares its name to usmwin process name
	_log("before p_Process32First\n");
    if (p_Process32First(hProcSnap, &stPE32)) 
    { 
        do 
        { 
            if (OSGetProcessModule(stPE32.th32ProcessID))
            { 
			     scolPIDsSize++;
				 scolPIDs = (DWORD *)realloc(scolPIDs, sizeof(DWORD)*(scolPIDsSize));
				 scolPIDs[scolPIDsSize-1] = (DWORD)stPE32.th32ProcessID;
            } 
        } 
        while (p_Process32Next(hProcSnap, &stPE32)); 
    } 
    CloseHandle (hProcSnap); 
    



	CloseTOOLHELP32();

	_log("OSIsScolRunning end : scolPIDsSize=%d\n",scolPIDsSize);
    if (scolPIDsSize == 0)
		return FALSE;

	return TRUE;
}





















/***********************************************************************************/
/***********************************************************************************/
/**                                                                               **/
/**     E X T E R N A L        B O D Y                                            **/
/**                                                                               **/
/***********************************************************************************/
/***********************************************************************************/





/***************************************/
/* IsScolRunning                       */
/*                                     */
/* replace old IsScolRunning function  */
/* return TRUE if one or several scol  */
/* processes are detected.             */
/***************************************/
BOOL IsScolRunning ()
{
DWORD winVersion;

    if ((winVersion = iGetWinVersion()) == I_WINVER_NULL)
		return false;

	//initialization of global data
	if (scolPIDs)
	{
		free (scolPIDs);
		scolPIDs = NULL;
	}
	scolPIDsSize = 0;

    if (winVersion == I_WINVER_NT4)
        // NT 4
        return NTIsScolRunning();
    else
        // others
        return OSIsScolRunning();
}








/***************************************/
/* KillScol                            */
/*                                     */
/* kill all processes referenced in    */
/* scolProcID                          */
/* return TRUE is all Scol processes   */
/* have been killed. FALSE if not      */
/***************************************/
BOOL KillScol ()
{
HANDLE hProc;

    if ((scolPIDsSize != 0) && (scolPIDs != NULL))
		for (DWORD i=0; i < scolPIDsSize; i++)
		{
			hProc = OpenProcess (PROCESS_TERMINATE, FALSE, scolPIDs[i]);

			if (TerminateProcess (hProc, 0) == 0)
				return FALSE;
		}
	
	return TRUE;
}