campo-sirio/setup/utils.cpp

759 lines
22 KiB
C++
Executable File
Raw Blame History

#include "wxinc.h"
#include "utils.h"
#include <lm.h>
#include <shlobj.h>
#include <psapi.h>
#pragma comment(lib, "Psapi.lib")
DWORD FindProcessId(LPCTSTR strProcess)
{
DWORD* aProcesses = NULL;
DWORD nItems = 0, nFound = 0, i = 0;
DWORD pid = 0;
for (nItems = 256; ; nItems *= 2)
{
DWORD cbNeeded = 0;
free(aProcesses);
aProcesses = (DWORD*)calloc(nItems, sizeof(DWORD));
if (!EnumProcesses(aProcesses, nItems*sizeof(DWORD), &cbNeeded))
{
free(aProcesses);
return FALSE;
}
nFound = cbNeeded / sizeof(DWORD);
if (nFound < nItems)
break;
}
for (i = 0; i < nFound && pid == 0; i++) if (aProcesses[i])
{
HANDLE hProcess = ::OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );
if (hProcess != NULL)
{
HMODULE hMod;
DWORD cbNeeded;
if (::EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
{
TCHAR szProcessName[MAX_PATH] = { 0 };
::GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR) );
if (strstr(szProcessName, strProcess) != NULL)
pid = aProcesses[i];
}
// Release the handle to the process.
CloseHandle( hProcess );
}
}
free(aProcesses);
return pid;
}
//metodo per farsi ritornare l'ID di sessione e quindi sapere se si e' in modalita' termserv (win2000,win2003,win2008)
int GetSessionId()
{
DWORD session = 0;
::ProcessIdToSessionId(GetCurrentProcessId(), &session);
return (int) session;
}
//lista delle versioni di windows
#define WUNKNOWNSTR _T("unknown Windows version")
#define W2KSTR _T("Windows 2000")
#define WXPSTR _T("Windows XP")
#define W2003STR _T("Windows Server 2003")
#define WVISTASTR _T("Windows Vista")
#define W2008STR _T("Windows Server 2008")
#define W7STR _T("Windows 7")
#define W8STR _T("Windows 8")
//metodo per provare a trovare la versione di windows
bool GetWinVer(LPTSTR lpszVersion, int nVersionSize, int& nVersion, bool& bIsServer)
{
nVersion = WUNKNOWN;
LPCTSTR cp = WUNKNOWNSTR;
OSVERSIONINFOEX osinfo; ZeroMemory(&osinfo, sizeof(osinfo));
osinfo.dwOSVersionInfoSize = sizeof(osinfo);
if (::GetVersionEx((OSVERSIONINFO*)&osinfo))
{
const DWORD dwPlatformId = osinfo.dwPlatformId;
const DWORD dwMinorVersion = osinfo.dwMinorVersion;
const DWORD dwMajorVersion = osinfo.dwMajorVersion;
const DWORD dwBuildNumber = osinfo.dwBuildNumber & 0xFFFF; // Win 95 needs this
const WORD wProductType = osinfo.wProductType;
if (dwPlatformId == VER_PLATFORM_WIN32_NT && dwMajorVersion >= 5)
{
bIsServer = wProductType > VER_NT_WORKSTATION;
if (dwMajorVersion == 5)
{
switch (dwMinorVersion)
{
case 0: cp = W2KSTR; nVersion = W2K; break;
case 1: cp = WXPSTR; nVersion = WXP; break;
default: cp = W2003STR; nVersion = W2003; break;
}
}
else if (dwMajorVersion == 6)
{
switch (dwMinorVersion)
{
case 0:
if (wProductType == VER_NT_WORKSTATION)
{ cp = WVISTASTR; nVersion = WVISTA; }
else
{ cp = W2008STR; nVersion = W2008;}
break;
case 1: cp = W7STR; nVersion = W7; break;
default: cp = W8STR; nVersion = W8; break;
}
}
else if (dwMajorVersion > 6) // ???
{
cp = W8STR;
nVersion = W8;
}
}
}
if (lpszVersion != NULL && nVersionSize > 0)
_tcsncpy(lpszVersion, cp, nVersionSize-1);
return nVersion != WUNKNOWN;
}
wxString GetWindowsProgramDirectory()
{
//scelta della directory di installazione di default
TCHAR strFolder[MAX_PATH];
::SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, strFolder);
return strFolder;
}
wxString GetWindowsDesktopDirectory()
{
//scelta della directory di installazione di default
TCHAR strFolder[MAX_PATH];
::SHGetFolderPath(NULL, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, strFolder);
return strFolder;
}
wxString GetDefaultDestination()
{
wxString strDest;
strDest = GetWindowsProgramDirectory();
if (strDest.IsEmpty())
{
// Forse <20> la cartella base dove <20> installato Word?
wxFileType* pDoc = wxTheMimeTypesManager->GetFileTypeFromExtension(wxT("doc"));
if (pDoc != NULL)
{
wxFileName strFilename = pDoc->GetOpenCommand(wxT("pippo.doc"));
while (strFilename.GetDirCount() > 1)
strFilename.RemoveLastDir();
strDest = strFilename.GetPath().After('"');
if (strDest.StartsWith(wxT("C\\")))
strDest = wxT("C:") + strDest.Mid(1);
}
}
return strDest;
}
//metodo per avere la lista delle condivisioni remote connesse al computer (preso da MSDN)
size_t ListNetworkDisks(wxArrayString& asList)
{
DWORD dwResult, dwResultEnum;
HANDLE hEnum;
DWORD cbBuffer = 16384; // 16K is a good size
DWORD cEntries = -1; // enumerate all possible entries
LPNETRESOURCE lpnrLocal; // pointer to enumerated structures
DWORD i;
//
// Call the WNetOpenEnum function to begin the enumeration.
//
dwResult = WNetOpenEnum(RESOURCE_CONNECTED, // connected resources
RESOURCETYPE_DISK, // only disks
0, // enumerate all resources
NULL, // NULL first time the function is called
&hEnum); // handle to the resource
if (dwResult != NO_ERROR)
{
//
// Process errors with an application-defined error handler.
//
//NetErrorHandler(hwnd, dwResult, (LPSTR)"WNetOpenEnum");
//return false;
return 0;
}
//
// Call the GlobalAlloc function to allocate resources.
//
lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
if (lpnrLocal == NULL)
return 0;
do
{
//
// Initialize the buffer.
//
ZeroMemory(lpnrLocal, cbBuffer);
//
// Call the WNetEnumResource function to continue
// the enumeration.
//
dwResultEnum = WNetEnumResource(hEnum, // resource handle
&cEntries, // defined locally as -1
lpnrLocal, // LPNETRESOURCE
&cbBuffer); // buffer size
//
// If the call succeeds, loop through the structures.
//
if (dwResultEnum == NO_ERROR)
{
for(i = 0; i < cEntries; i++)
{
asList.Add(lpnrLocal[i].lpLocalName);
}
}
// Process errors.
//
else if (dwResultEnum != ERROR_NO_MORE_ITEMS)
{
//NetErrorHandler(hwnd, dwResultEnum, (LPSTR)"WNetEnumResource");
break;
}
}
//
// End do.
//
while(dwResultEnum != ERROR_NO_MORE_ITEMS);
//
// Call the GlobalFree function to free the memory.
//
::GlobalFree((HGLOBAL)lpnrLocal);
//
// Call WNetCloseEnum to end the enumeration.
//
dwResult = ::WNetCloseEnum(hEnum);
if(dwResult != NO_ERROR)
{
//
// Process errors.
//
//NetErrorHandler(hwnd, dwResult, (LPSTR)"WNetCloseEnum");
return 0;
}
return asList.GetCount();
}
//metodo per avere un array con la lista dei path delle condivisioni locali
size_t ListSharedDirectories(wxArrayString& asList)
{
NET_API_STATUS res = ERROR_MORE_DATA;
while (res == ERROR_MORE_DATA)
{
PSHARE_INFO_502 shi;
DWORD nEntriesRead = 0, nTotalEntries = 0, nResume = 0;
res = NetShareEnum(NULL, 502, (LPBYTE *)&shi, -1, &nEntriesRead, &nTotalEntries, &nResume);
if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA)
{
for (DWORD i = 0; i < nEntriesRead; i++)
{
wxString strPath(shi[i].shi502_path);
if (!strPath.IsEmpty())
{
strPath.MakeLower();
asList.Add(strPath);
}
} //for(DWORD i...
NetApiBufferFree(shi);
} //if(res ==...
} //while (res==ERROR_MORE_DATA...
return asList.GetCount();
}
//Magico metodo per stabilire se una directory e' condivisa ed e' su un disco locale!!
bool IsSharedDirectory (const wxString& strDir)
{
bool found = false;
wxString strDataDir = strDir.Lower();
strDataDir.Replace ("/", "\\");
wxArrayString asList;
ListSharedDirectories(asList);
for (size_t i = 0; i < asList.GetCount(); i++)
{
const wxString& strPath = asList[i];
//se trova la directory di studio condivisa ed e' su disco locale -> server
if (strPath.Len() > 3 && strDir.StartsWith(strPath))
{
found = true;
break;
}
} //for(DWORD i...
return found;
}
//finestre per messaggi vari
//---------------------------------------------------------------------------------
bool ErrorBox(const wxString str)
{
wxMessageBox(str, APPNAME, wxOK | wxICON_ERROR);
return false;
}
bool MessageBox(const wxString str)
{
wxMessageBox(str, APPNAME, wxOK | wxICON_INFORMATION);
return false;
}
bool WarningBox(const wxString str)
{
wxMessageBox(str, APPNAME, wxOK | wxICON_EXCLAMATION);
return false;
}
bool YesNoBox(const wxString str)
{
int nAnswer = wxMessageBox(str, APPNAME, wxYES_NO | wxICON_QUESTION);
if (nAnswer == wxYES)
return true;
else
return false;
}
//classe per gestire i .Ini di campo
//-----------------------------------------------------------------------------------
bool CampoIniFile::GetFirstGroup(wxString& strGroup, long& nIndex)
{
m_asGroups.Clear();
char bufferone[1024*16];
::GetPrivateProfileSectionNames(bufferone, sizeof(bufferone), m_strIniName);
const char* inizio = bufferone;
for (const char* b = bufferone; ; b++) if (*b == '\0')
{
if (*inizio)
{
m_asGroups.Add(inizio);
inizio = b+1;
}
else
break;
}
nIndex = 0;
return GetNextGroup(strGroup, nIndex);
}
bool CampoIniFile::GetNextGroup(wxString& strGroup, long& nIndex)
{
const bool ok = nIndex >= 0 && nIndex < (long)m_asGroups.GetCount();
if (ok)
strGroup = m_asGroups[nIndex++];
return ok;
}
bool CampoIniFile::DeleteGroup(const wxString strGroup)
{
return ::WritePrivateProfileString(m_strGroup, NULL, NULL, m_strIniName) != 0;
}
bool CampoIniFile::GetFirstEntry(wxString& strEntry, long& nIndex)
{
m_asEntries.Clear();
char bufferone[1024*32];
::GetPrivateProfileSection(m_strGroup, bufferone, sizeof(bufferone), m_strIniName);
const char* pInizio = bufferone;
for (const char* b = bufferone; ; b++) if (*b == '\0')
{
if (*pInizio)
{
wxString strWrk = pInizio;
strWrk = strWrk.BeforeFirst('=');
strWrk.Trim();
//prende solo il nome della variabile per completare la lista! dopo l'= ci sarebbe il valore
m_asEntries.Add(strWrk);
pInizio = b+1;
}
else
break;
}
nIndex = 0;
return GetNextEntry(strEntry, nIndex);
}
bool CampoIniFile::GetNextEntry(wxString& strEntry, long& nIndex)
{
const bool ok = nIndex >= 0 && nIndex < (long)m_asEntries.GetCount();
if (ok)
strEntry = m_asEntries[nIndex++];
return ok;
}
wxString CampoIniFile::Get(const wxString strVariable) const
{
wxString strOutString;
char* buffer = strOutString.GetWriteBuf(256);
::GetPrivateProfileString(m_strGroup, strVariable, "", buffer, 256, m_strIniName);
strOutString.UngetWriteBuf(); //sblocca la memoria senno' la stringa resta per sempre!!!
return strOutString;
}
bool CampoIniFile::GetBool(const wxString strVariable) const
{
const char chVal = Get(strVariable)[0];
return chVal == 'X' || chVal == 'Y' || chVal == '1';
}
int CampoIniFile::GetInt(const wxString strVariable) const
{
return wxAtoi(Get(strVariable));
}
bool CampoIniFile::Set(const wxString strVariable, const wxString strValue)
{
return ::WritePrivateProfileString(m_strGroup, strVariable, strValue, m_strIniName) != 0;
}
bool CampoIniFile::Set(const wxString strVariable, const int uValue)
{
wxString strValue;
strValue << uValue;
return ::WritePrivateProfileString(m_strGroup, strVariable, strValue, m_strIniName) != 0;
}
//costruttore
CampoIniFile::CampoIniFile(const wxString strIniPath, wxString strGroup)
: m_strIniName(strIniPath), m_strGroup(strGroup)
{
}
//metodo per sapere che cavolo di tipo di installazione sta esaminando (serve per leggere e scrivere...
//...correttamente il campo.ini
InstallationType CampoIniFile::GetInstallationType() const
{
InstallationType nType = (InstallationType)GetInt("Type");
if (nType < it_standalone || nType > it_client)
{
nType = it_standalone; //di base e' standalone
const bool bTestDataBase = GetBool("TestDatabase");
const bool bTestPrograms = GetBool("TestPrograms");
if (bTestDataBase) //se puo' manipolare i dati e' StandAlone o Server..
{
//ma e' Standalone o Server?
//se la directory dei dati e' condivisa in scrittura e' un server (almeno al 99%)
const wxString strStudy = Get("Study");
if (IsSharedDirectory(strStudy))
nType = it_server; //e' server
}
else //..senno' e' client
nType = it_client;
}
return nType;
}
//classe per le progind con dimensioni
//--------------------------------------------------------------------------------------
#define CPD_FLAGS wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT | wxPD_ELAPSED_TIME | wxPD_ESTIMATED_TIME | wxPD_REMAINING_TIME
CampoProgressDialog::CampoProgressDialog(const wxString& strTitle, int nMaximum, wxWindow* pParent)
: wxProgressDialog(strTitle, wxEmptyString, nMaximum, pParent, CPD_FLAGS)
{
SetSize(wxSize(600, -1));
Center();
}
//gestione filesystem
//--------------------------------------------------------------------------------------
bool CheckAndMakeDir(const wxString& strDir, const wxString& strMsg)
{
if (!wxDir::Exists(strDir))
{
if (!wxFileName::Mkdir(strDir, 0x777, wxPATH_MKDIR_FULL))
{
wxString strError = "Impossibile creare la cartella ";
strError += strMsg;
strError += " ";
strError += strDir;
strError += "\nAssicurarsi di avere i permessi di scrittura e che vi sia spazio a sufficienza";
return ErrorBox(strMsg);
}
}
if (!strMsg.IsEmpty()) //se il messaggio e' vuoto NON deve fare alcun controllo (installazione sistema)
{
wxDir dirDir(strDir);
if (dirDir.HasFiles()) //se la dir di destinazione dovesse esistere gi<67> (installazione abortita) almeno sia vuota
return ErrorBox("La cartella di destinazione non e' vuota!\nInstallazione interrotta!");
}
return true;
}
bool CopiaFile(const wxString& strFileSrc, const wxString& strFileDest)
{
//serve per ritrovare eventuali sottodirectory
wxFileName fnFileDest(strFileDest);
if (!fnFileDest.DirExists())
fnFileDest.Mkdir(0777, wxPATH_MKDIR_FULL);
bool ok = ::wxCopyFile(strFileSrc, strFileDest);
if (ok)
{
DWORD dwFileAttribs = ::GetFileAttributes(strFileDest);
if (dwFileAttribs & FILE_ATTRIBUTE_READONLY)
{
dwFileAttribs &= ~FILE_ATTRIBUTE_READONLY;
::SetFileAttributes(strFileDest, dwFileAttribs);
}
}
else
{
wxString strErr = "Impossibile copiare il file ";
strErr += strFileSrc;
strErr += " in ";
strErr += strFileDest;
strErr += "\nInstallazione interrotta!";
ErrorBox(strErr);
}
return ok;
}
void NormalizeSlash(wxString& strFileName)
{
strFileName.Replace("\\", "/"); // Trasforma i backslash in slash
strFileName.Replace("//", "/"); // Elimina i doppi slash
}
//metodi per unzippare i files
//-------------------------------------------------------------------------------
static size_t GetZipList(const char* strZipFile, wxArrayString& aFiles)
{
wxFFileInputStream fin(strZipFile);
wxZipInputStream zip(fin);
for (wxZipEntry* z = zip.GetNextEntry(); z; z = zip.GetNextEntry())
{
const wxString str = z->GetInternalName();
aFiles.Add(str);
}
return aFiles.GetCount();
}
bool UnzipFile(const wxString& strSrcFile, const wxString& strDestDir)
{
//se il file da unzippare <20> su un disco remoto, lo copia in locale per unzipparlo e alla fine elimina la copia..
//..<2E> importante per velocizzare l'aggiornamento da disco
wxString strZipFile = strSrcFile;
const int nDriveType = ::GetDriveType(strZipFile.Left(3));
bool bTemp = nDriveType == DRIVE_REMOTE;
if (bTemp)
{
wxBusyCursor wait;
const wxString strFullAppName = PRODUCT + " " + RESELLER;
wxDialog dlgWait(NULL, wxID_ANY, strFullAppName, wxDefaultPosition, wxSize(480,80), wxCAPTION);
wxString str; str << "Copia di " << strSrcFile << "\nAttendere prego...";
wxStaticText* text = new wxStaticText(&dlgWait, wxID_ANY, wxEmptyString, wxPoint(4,4), wxSize(472,72),
wxST_NO_AUTORESIZE || wxST_DOTS_MIDDLE);
text->SetLabel(str);
dlgWait.Centre();
dlgWait.Show(true);
dlgWait.Update();
strZipFile = wxFileName::CreateTempFileName("tmp");
if (!wxCopyFile(strSrcFile, strZipFile))
{
strZipFile = strSrcFile;
bTemp = false;
}
dlgWait.Show(false);
}
wxArrayString aFiles;
const size_t files = GetZipList(strZipFile, aFiles);
CampoProgressDialog pi(strZipFile, (int)files);
for (unsigned int f = 0; f < files; f++)
{
const wxString& strFileName = aFiles[f];
if (!pi.Update(f, strFileName))
break;
if (wxEndsWithPathSeparator(strFileName) || strFileName.Find('.') < 0) // Is dir name
{
wxString strOutDir = strDestDir;
if (!wxEndsWithPathSeparator(strOutDir))
strOutDir += wxFILE_SEP_PATH;
strOutDir += strFileName;
CheckAndMakeDir(strOutDir, wxEmptyString);
}
else
{
wxFFileInputStream fstr(strZipFile);
wxZipInputStream fin(fstr);
wxZipEntry* entry = NULL;
do entry = fin.GetNextEntry();
while (entry && entry->GetInternalName() != strFileName);
if (entry && fin.OpenEntry(*entry))
{
wxString strOutFile = strDestDir;
if (!wxEndsWithPathSeparator(strOutFile) && !wxIsPathSeparator(strFileName[0]))
strOutFile += wxFILE_SEP_PATH;
strOutFile += strFileName;
wxString strPath;
::wxSplitPath(strOutFile, &strPath, NULL, NULL);
CheckAndMakeDir(strPath, wxEmptyString);
wxFileOutputStream fout(strOutFile);
fout.Write(fin);
fout.Close();
fin.CloseEntry();
if (strOutFile.EndsWith("res.zip"))
UnzipFile(strOutFile , strPath);
}
}
}
if (bTemp)
wxRemoveFile(strZipFile);
return files > 0;
}
// metodi per raccattare il reseller del cd che si sta installando
//---------------------------------------------------------------------------------------
static const char* const encryption_key = "QSECOFR-";
//Ritorna in chiaro la stringa crittata che gli viene passata
static wxString CampoDecode(const wxString& data)
{
wxString tmp;
for (size_t i = 0; data[i]; i++)
tmp << wxChar(data[i] - (i < 8 ? encryption_key[i] : tmp[i - 8]));
return tmp;
}
static wxString FindOemIniPath()
{
wxString strWorkingDir = wxFileName::GetCwd();
strWorkingDir.MakeLower();
if (!strWorkingDir.EndsWith("setup"))
strWorkingDir << "/setup";
strWorkingDir << "/oem.ini";
return strWorkingDir;
}
//trova il numero del reseller
int FindReseller()
{
CampoIniFile iniOemMain(FindOemIniPath(), "MAIN");
const int nOem = iniOemMain.GetInt("OEM");
return nOem > 0 ? nOem : 0;
}
//stringhe globali per avere sempre a disposizione Reseller, Product e Appname in ogni momento (vanno sulle finestre)
static wxString _strReseller, _strProduct, _strAppname, _strLicence, _strLogo, _strIcon, _strTheme;
//lettore del oem.ini che contiene tutte le info necessarie del CD
static void ReadOemIni()
{
//si basa sul reseller che <20> la guida di ogni parametro
if (_strReseller.IsEmpty())
{
const int oem = FindReseller();
//trovato il numero del reseller legge il paragrafo corrispondente in oem.ini
const wxString strOemIniPath = FindOemIniPath();
wxString strParagraph;
strParagraph << "OEM_" << oem;
CampoIniFile iniOem(strOemIniPath, strParagraph);
//raccatta le informazioni dal paragrafo corretto del produttore
//prima quelle crittate
const wxString strCriptedAppname = iniOem.Get("Name");
const wxString strCriptedProduct = iniOem.Get("Product");
const wxString strCriptedReseller = iniOem.Get("Reseller");
//adesso viene il bello! Deve decrittarle...ci vuole ENIGMA!
_strAppname = CampoDecode(strCriptedAppname);
_strProduct = CampoDecode(strCriptedProduct);
_strReseller = CampoDecode(strCriptedReseller);
//dati non crittati (a disposizione di cani e porci insomma...)
_strIcon = iniOem.Get("Icon");
_strLicence = iniOem.Get("Licence");
_strLogo = iniOem.Get("Logo");
_strTheme = iniOem.Get("Themes");
}
}
static wxString ReturnOrLoad(const wxString& var)
{
if (var.IsEmpty())
ReadOemIni();
return var;
}
//metodi per ritornare la stringa di competenza; si basano tutti su ReadOemIni
wxString Reseller()
{ return ReturnOrLoad(_strReseller); }
wxString Product()
{ return ReturnOrLoad(_strProduct); }
wxString Appname()
{ return ReturnOrLoad(_strAppname); }
wxString Licence()
{ return ReturnOrLoad(_strLicence); }
wxString Logo()
{ return ReturnOrLoad(_strLogo); }
wxString Icon()
{ return ReturnOrLoad(_strIcon); }
wxString Theme()
{ return ReturnOrLoad(_strTheme); }