#pragma once
#include <vector>
#include "ExecCmd.h"
#include "VersionCompare.h"
#include "Path.h"
#include "File.h"
#include "DownloadDialogSupport.h"
#include "DownloadDialog.h"
//in tutti i percorsi viene sostituito #APPPATH con il percorso dell'applicazione corrente, #SYSTEMPATH con la directory System del computer e #WINDOWSPATH con la directory di installazione di Windows, #TEMPPATH con la directory temporanea
//in all the paths we replace the string constant #APPPATH with the current path of the application and #SYSTEMPATH with the system directory of the computer, #TEMPPATH with the temp directory
#define c_APPPATH "#APPPATH"
#define c_SYSTEMPATH "#SYSTEMPATH"
#define c_WINDOWSPATH "#WINDOWSPATH"
#define c_TEMPPATH "#TEMPPATH"
enum component_type
{
cmd, //shell command
msi, //windows installer setup
openfile //ShellExecute call to open a file
};
struct installedcheck
{
virtual bool IsInstalled() = 0;
};
struct installedcheck_check_registry_value : public installedcheck
{
CString path; //percorso del registry
CString fieldname; //nome del campo del registry
CString fieldvalue; //valore del registry bisogna convertirlo in base al tipo
CString fieldtype; //tipo del campo nel registry : REG_DWORD (long) o REG_SZ (string)
CString comparison; //tipo di comparazione : match (verifica se le due stringhe sono uguali) version (che tratta le due stringhe come versioni e quindi se quella richiesta � minore bisogna installare altrimenti no)
virtual bool IsInstalled()
{
try
{
HKEY l_HKey;
LONG l_result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
path,
0,
KEY_READ,
&l_HKey);
if (l_result != ERROR_SUCCESS)
return false;
if (fieldtype == "REG_DWORD")
{
DWORD l_value;
DWORD l_dwordLen = sizeof(DWORD);
DWORD l_type = REG_DWORD;
l_result = RegQueryValueEx(l_HKey,fieldname, NULL, &l_type, (LPBYTE)&l_value, &l_dwordLen);
if (l_result != ERROR_SUCCESS)
{
RegCloseKey(l_HKey);
return false;
}
RegCloseKey(l_HKey);
DWORD l_checkValue;
if (sscanf(fieldvalue, "%d", &l_checkValue) != 1)
{
AfxMessageBox("Invalid registry value to check expected DWORD.", MB_OK|MB_ICONSTOP);
return false;
}
if (comparison == "match")
{
if (l_checkValue == l_value)
return true;
else
return false;
}
else if (comparison == "version")
{
if (l_checkValue <= l_value)
return true;
else
return false;
}
else
{
AfxMessageBox("Invalid comparison type, expected match or version.", MB_OK|MB_ICONSTOP);
return false;
}
}
else if (fieldtype == "REG_SZ")
{
DWORD l_dwordLen = 0;
DWORD l_type = REG_SZ;
l_result = RegQueryValueEx(l_HKey,fieldname, NULL, &l_type, NULL, &l_dwordLen);
if (l_result != ERROR_SUCCESS)
{
RegCloseKey(l_HKey);
return false;
}
TCHAR * l_value = new TCHAR[l_dwordLen+1];
ZeroMemory(l_value,l_dwordLen+1);
l_result = RegQueryValueEx(l_HKey,fieldname, NULL, &l_type, (LPBYTE)l_value, &l_dwordLen);
if (l_result != ERROR_SUCCESS)
{
RegCloseKey(l_HKey);
return false;
}
RegCloseKey(l_HKey);
if (comparison == "match")
{
if (fieldvalue == l_value)
return true;
else
return false;
}
else if (comparison == "version")
{
if ( DVLib::stringVersionCompare(fieldvalue, l_value) <= 0 )
return true;
else
return false;
}
else
{
AfxMessageBox("Invalid comparison type, expected match or version.", MB_OK|MB_ICONSTOP);
return false;
}
}
else
{
RegCloseKey(l_HKey);
AfxMessageBox("Invalid registry type", MB_OK|MB_ICONSTOP);
return false;
}
}
catch(...)
{
return false;
}
}
};
struct installedcheck_check_file : public installedcheck
{
CString filename; //percorso del file da cercare
CString fileversion; //versione del file (se "" non viene verificata la versione ma solo la presenza del file)
CString comparison; //tipo di comparazione : match (verifica se le due stringhe sono uguali) version (che tratta le due stringhe come versioni e quindi se quella richiesta � minore bisogna installare altrimenti no)
virtual bool IsInstalled()
{
try
{
if (DVLib::FileExists(filename))
{
if (fileversion.GetLength()>0)
{
CString l_FileVersion = DVLib::GetFileVersionString(filename);
if (comparison == "match")
{
if (l_FileVersion == fileversion)
return true;
else
return false;
}
else if (comparison == "version")
{
//se la versione � uguale o maggiore
if (DVLib::stringVersionCompare(l_FileVersion, fileversion) >= 0)
return true;
else
return false;
}
else
{
AfxMessageBox("Invalid comparison type, expected match or version.", MB_OK|MB_ICONSTOP);
return false;
}
}
else
return true;
}
else
return false;
}
catch(...)
{
return false;
}
}
};
struct component
{
//tipo di componente: cmd, msi, openfile
component_type type;
//descrizione
CString description;
//filtro che indica il minimo sistema operativo in cui lanciare il componente (estremo escluso)
CString os_filter_greater;
//filtro che indica il massimo sistema operativo in cui lanciare il componente (estremo escluso)
CString os_filter_smaller;
//filtro che indica il filtro per lingua del sistema operativo (es. Italy = 1040, English - United Kingdom = 2057, English - United States = 1033)
CString os_filter_lcid;
//Testo visualizzato quando si installa il componente
CString installmessage;
//testo da visualizzare a fine installazione (se vuoto non visualizza niente)
CString installcompletemessage;
//true per forzare il reboot al termine dell'installazione altrimenti false
bool mustreboot;
//classi per gestire la verifica se il componente � installato o no
std::vector<installedcheck*> installedchecks;
//Informazioni sull'eventuale download dei componenti (fa riferimento al nodo downloaddialog all'interno di component, se non � presente non viene scaricato nessun componente)
DVLib::DownloadGroupConfiguration DownloadDialogConfiguration;
//indica se il componente contiene o meno dei componenti da scaricare (in pratica dice se il nodo downloaddialog � presente o no)
bool ContainsDownloadComponent;
//scarica gli eventuali componenti necesari e restituisce true se il download ha avuto successo
bool DownloadComponents()
{
try
{
if (ContainsDownloadComponent)
return RunDownloadDialog(DownloadDialogConfiguration);
else
return true;
}
catch(...)
{
return false;
}
}
//virtual bool ExecWait(DWORD * pExitCodes) = 0;
//funzione virtuale specifica per il tipo di componente
virtual bool Exec() = 0;
virtual DWORD GetExitCode() = 0;
virtual bool IsExecuting() = 0;
bool IsInstalled()
{
if (installedchecks.size() == 0)
return false;
bool l_installed = true;
for (size_t j = 0; j < installedchecks.size(); j++)
{
l_installed = l_installed && installedchecks[j]->IsInstalled();
}
return l_installed;
}
};
struct process_component : public component
{
//Informazioni sul processo in eseguzione
PROCESS_INFORMATION m_process_info;
virtual DWORD GetExitCode()
{
DWORD l_ExitCode;
if (GetExitCodeProcess(m_process_info.hProcess, &l_ExitCode))
{
return l_ExitCode;
}
else
{
_ASSERT(false);
throw -1;
}
}
virtual bool IsExecuting()
{
DWORD l_ExitCode;
if (GetExitCodeProcess(m_process_info.hProcess, &l_ExitCode))
{
if (l_ExitCode == STILL_ACTIVE)
return true;
else
return false;
}
else
return false;
}
};
struct cmd_component : public process_component
{
CString command;
/* virtual bool ExecWait(DWORD * pExitCodes)
{
return DVLib::ExecCmdAndWait(command, pExitCodes);
};*/
virtual bool Exec()
{
return DVLib::ExecCmd(command, &m_process_info);
};
};
struct msi_component : public process_component
{
CString package;
CString cmdparameters; // es. "/qn REBOOT=ReallySuppress"
// msi install cmd-line
//const TCHAR g_tszMsiCmdLine[] = _T("Msiexec /I %s REBOOT=ReallySuppress");
/*virtual bool ExecWait(DWORD * pExitCodes)
{
CString l_command = "msiexec /I ";
l_command += "\"";
l_command += package;
l_command += "\"";
l_command += " ";
l_command += cmdparameters;
//if (silent)
// l_command += " /qn";
//if (suppressreboot)
// l_command += " REBOOT=ReallySuppress";
return DVLib::ExecCmdAndWait(l_command, pExitCodes);
};*/
virtual bool Exec()
{
CString l_command = "msiexec /I ";
l_command += "\"";
l_command += package;
l_command += "\"";
l_command += " ";
l_command += cmdparameters;
//if (silent)
// l_command += " /qn";
//if (suppressreboot)
// l_command += " REBOOT=ReallySuppress";
return DVLib::ExecCmd(l_command, &m_process_info);
};
};
//open a file with a shellexecute call
struct openfile_component : public component
{
CString file; //file to open. Can be a web link or a standard file
virtual bool Exec()
{
HINSTANCE l_hInstance = ShellExecute(NULL,NULL,file,NULL,NULL,SW_SHOWNORMAL);
if ( l_hInstance <= (HINSTANCE)32 )
return false;
else
return true;
}
virtual DWORD GetExitCode()
{
return ERROR_SUCCESS;
}
virtual bool IsExecuting()
{
return false;
}
};
struct installerSetting
{
CString dialog_caption;
CString dialog_message;
CString dialog_bitmap;
CString install_caption;
CString cancel_caption;
CString reinstallflag_caption;
CString status_installed;
CString status_notinstalled;
CString failed_exec_command_continue;
CString installation_completed;
CString reboot_required;
CString dialog_install_next;
CString dialog_install_skip;
CString installing_component_wait;
std::vector<component*> components;
};
// HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
#define c_dotNetInstaller "dotNetInstallerBoot"
//#define c_RunOnce "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce"
#define c_Reg_Run "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
inline void InsertRegistryRun()
{
try
{
HKEY l_HKey;
LONG l_result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
c_Reg_Run,
0,
KEY_WRITE,
&l_HKey);
if (l_result != ERROR_SUCCESS)
return;
CString l_ExeName = DVLib::GetAppFullName();
RegSetValueEx(l_HKey, c_dotNetInstaller,0,REG_SZ,(LPBYTE)(LPCTSTR)l_ExeName, (DWORD)(l_ExeName.GetLength()+1) );
RegCloseKey(l_HKey);
}
catch(...)
{
_ASSERT(false);
}
};
inline void RemoveRegistryRun()
{
try
{
HKEY l_HKey;
LONG l_result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
c_Reg_Run,
0,
KEY_WRITE,
&l_HKey);
if (l_result != ERROR_SUCCESS)
return;
RegDeleteValue(l_HKey, c_dotNetInstaller);
RegCloseKey(l_HKey);
}
catch(...)
{
_ASSERT(false);
}
};
// ==========================================================================
// InitiateReboot()
//
// Purpose: initiates a system reboot
//
// ==========================================================================
inline BOOL InitiateReboot()
{
HANDLE hToken; // handle to process token
TOKEN_PRIVILEGES tkp; // pointer to token structure
try
{
// Get the current process token handle so we can get shutdown
// privilege.
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
// return FALSE;
}
// Get the LUID for shutdown privilege.
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
&tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; // one privilege to set
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Get shutdown privilege for this process.
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES) NULL, 0);
// Cannot test the return value of AdjustTokenPrivileges.
if (GetLastError() != ERROR_SUCCESS)
{
// return FALSE;
}
}
catch (...)
{
}
return ExitWindowsEx( EWX_REBOOT, 0);
}
inline CString ValidatePath(LPCTSTR p_Path)
{
//ApplicationPath
CString l_CurrentPath = DVLib::GetAppPath();
//SystemPath
TCHAR l_bufferSystem[MAX_PATH+1];
ZeroMemory(l_bufferSystem,MAX_PATH+1);
GetSystemDirectory(l_bufferSystem, MAX_PATH+1);
//WindowsPath
TCHAR l_bufferWindows[MAX_PATH+1];
ZeroMemory(l_bufferWindows,MAX_PATH+1);
GetWindowsDirectory(l_bufferWindows, MAX_PATH+1);
//TempPath
TCHAR l_bufferTempPath[MAX_PATH+1];
ZeroMemory(l_bufferTempPath,MAX_PATH+1);
GetTempPath(MAX_PATH+1, l_bufferTempPath);
CString tmp = p_Path;
tmp.Replace(c_APPPATH, l_CurrentPath);
tmp.Replace(c_SYSTEMPATH, l_bufferSystem);
tmp.Replace(c_WINDOWSPATH, l_bufferWindows);
tmp.Replace(c_TEMPPATH, l_bufferTempPath);
return tmp;
}