#include "wxinc.h" #include "utils.h" #ifdef WIN32 #include #include #endif //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 W95STR _T("Windows 95") #define W95SP1STR _T("Windows 95 SP1") #define W95OSR2STR _T("Windows 95 OSR2") #define W98STR _T("Windows 98") #define W98SP1STR _T("Windows 98 SP1") #define W98SESTR _T("Windows 98 SE") #define WMESTR _T("Windows ME") #define WNT351STR _T("Windows NT 3.51") #define WNT4STR _T("Windows NT 4") #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 WCESTR _T("Windows CE") //metodo per provare a trovare la versione di windows bool GetWinVer(LPTSTR lpszVersion, int nVersionSize, int *pnVersion) { int nVersion = WUNKNOWN; LPCTSTR cp = WUNKNOWNSTR; OSVERSIONINFO osinfo; memset(&osinfo, 0, sizeof(osinfo)); osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (::GetVersionEx(&osinfo)) { DWORD dwPlatformId = osinfo.dwPlatformId; DWORD dwMinorVersion = osinfo.dwMinorVersion; DWORD dwMajorVersion = osinfo.dwMajorVersion; DWORD dwBuildNumber = osinfo.dwBuildNumber & 0xFFFF; // Win 95 needs this if ((dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) && (dwMajorVersion == 4)) { if ((dwMinorVersion < 10) && (dwBuildNumber == 950)) { cp = W95STR; nVersion = W95; } else if ((dwMinorVersion < 10) && ((dwBuildNumber > 950) && (dwBuildNumber <= 1080))) { cp = W95SP1STR; nVersion = W95SP1; } else if ((dwMinorVersion < 10) && (dwBuildNumber > 1080)) { cp = W95OSR2STR; nVersion = W95OSR2; } else if ((dwMinorVersion == 10) && (dwBuildNumber == 1998)) { cp = W98STR; nVersion = W98; } else if ((dwMinorVersion == 10) && ((dwBuildNumber > 1998) && (dwBuildNumber < 2183))) { cp = W98SP1STR; nVersion = W98SP1; } else if ((dwMinorVersion == 10) && (dwBuildNumber >= 2183)) { cp = W98SESTR; nVersion = W98SE; } else if (dwMinorVersion == 90) { cp = WMESTR; nVersion = WME; } } else if (dwPlatformId == VER_PLATFORM_WIN32_NT) { if (dwMajorVersion == 3) { cp = WNT351STR; nVersion = WNT351; } else if (dwMajorVersion == 4) { cp = WNT4STR; nVersion = WNT4; } else if (dwMajorVersion == 5) { switch (dwMinorVersion) { case 0: cp = W2KSTR; nVersion = W2K; break; case 1: cp = WXPSTR; nVersion = WXP; break; case 2: default: cp = W2003STR; nVersion = W2003; break; } } else if (dwMajorVersion == 6) { cp = WVISTASTR; nVersion = WVISTA; // TBI: Windows 2008 Server } else if (dwMajorVersion >= 7) { cp = W7STR; nVersion = W7; } } /* else if (dwPlatformId == VER_PLATFORM_WIN32_CE) { cp = WCESTR; nVersion = WCE; }*/ } if (lpszVersion != NULL && nVersionSize > 0) _tcsncpy(lpszVersion, cp, nVersionSize-1); if (pnVersion != NULL) *pnVersion = nVersion; return nVersion == WUNKNOWN; } wxString GetWindowsProgramDirectory() { //scelta della directory di installazione di default #ifdef WIN32 TCHAR strFolder[MAX_PATH]; ::SHGetFolderPath(NULL, CSIDL_PROGRAM_FILES, NULL, SHGFP_TYPE_CURRENT, strFolder); return strFolder; #endif } wxString GetDefaultDestination() { wxString strDest; strDest = GetWindowsProgramDirectory(); if (strDest.IsEmpty()) { // Forse è la cartella base dove è 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) { #ifdef WIN32 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... #endif 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 atoi(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 //-------------------------------------------------------------------------------------- void CheckAndMakeDir(const wxString& strDir, const wxString& strMsg) { if (!wxDir::Exists(strDir)) { const wxFileName fname(strDir + "\\*.*"); const wxArrayString& asDirs = fname.GetDirs(); wxString strCartella = fname.GetVolume(); strCartella += fname.GetVolumeSeparator(); for (size_t i = 0; i < asDirs.GetCount(); i++) { strCartella += "\\"; strCartella += asDirs[i]; if (!wxDir::Exists(strCartella) && !wxMkdir(strCartella, 0777)) { wxString strError = "Impossibile creare la cartella "; strError += strMsg; strError += " "; strError += strCartella; strError += "\nAssicurarsi di avere il permesso di scrittura sul disco e che vi sia spazio a sufficienza"; ErrorBox(strMsg); return; } } } 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 gia' (installazione abortita) almeno sia vuota { ErrorBox("La cartella di destinazione non e' vuota!\nInstallazione interrotta!"); return; } } } 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) { #ifdef WIN32 DWORD dwFileAttribs = ::GetFileAttributes(strFileDest); if (dwFileAttribs & FILE_ATTRIBUTE_READONLY) { dwFileAttribs &= ~FILE_ATTRIBUTE_READONLY; ::SetFileAttributes(strFileDest, dwFileAttribs); } #endif } 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 char* strSrcFile, const char* strDestDir) { //se il file da unzippare è su un disco remoto, lo copia in locale per unzipparlo e alla fine elimina la copia.. //..è 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 { wxZipInputStream fin(strZipFile, strFileName); 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(); 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; } //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 è la guida di ogni parametro if (_strReseller.IsEmpty()) { int oem = FindReseller(); if (oem < 0) oem = 0; //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! //usiamo una stringa del cazzo di appoggio per debuggare in tranquillità wxString strCaz = CampoDecode(strCriptedAppname); _strAppname = strCaz; strCaz = CampoDecode(strCriptedProduct); _strProduct = strCaz; strCaz = CampoDecode(strCriptedReseller); _strReseller = strCaz; //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"); } } //metodi per ritornare la stringa di competenza;si basano tutti su ReadOemIni wxString Reseller() { if (_strReseller.IsEmpty()) ReadOemIni(); return _strReseller; } wxString Product() { if (_strProduct.IsEmpty()) ReadOemIni(); return _strProduct; } wxString Appname() { if (_strAppname.IsEmpty()) ReadOemIni(); return _strAppname; } wxString Licence() { if (_strLicence.IsEmpty()) ReadOemIni(); return _strLicence; } wxString Logo() { if (_strLogo.IsEmpty()) ReadOemIni(); return _strLogo; } wxString Icon() { if (_strIcon.IsEmpty()) ReadOemIni(); return _strIcon; } wxString Theme() { if (_strTheme.IsEmpty()) ReadOemIni(); return _strTheme; }