//Il sorgente va scritto in notazione ungherese.
//Le variabili seguono la seguente regola: 'acronimo tipo'+'nome variabile cammellata'
//Es. wxArrayString 'as' + 'AcceptRefuse' -> asAcceptRefuse
#include "wxinc.h"
#include "); str += strTitle; str += wxT(" Questo programma vi guiderà passo a passo nell'installazione / aggiornamento del software. Leggere attentamente le istruzioni che saranno visualizzate nelle finestre di questo programma di installazione! Prima di proseguire con l'installazione / aggiornamento assicurarsi di avere effettuato il login a Windows con un utente di tipo 'Amministratore' di sistema. In caso si desideri aggiornare una postazione tipo server di APPNAME su cui sia attivo il gestore dei servizi di APPNAME, arrestare prima tale gestore dei servizi. E' possibile INSTALLARE APPNAME in un nuovo direttorio. E' possibile AGGIORNARE (scelta consigliata) una installazione di APPNAME gia' presente oppure INSTALLARE in un nuovo direttorio. Selezionare l'opzione desiderata nel riquadro sottostante. In caso di piu' di una installazione ");
strBody += wxT("presente sara' preselezionata la eventuale installazione di tipo Server, in quanto deve essere aggiornata per prima! ");
strBody += wxT(" In questo caso procedere all'aggiornamento di tale installazione Server e aggiornare successivamente le postazioni client ");
strBody += wxT("lanciando il programma APPNAME su di esse Prima di proseguire accertarsi che non vi sia alcuna sessione di APPNAME attiva! ");
strBody += wxT("Terminare quindi le eventuali sessioni di APPNAME attive e proseguire. La versione commerciale del software richiede l'installazione e la presenza della chiave hardware di protezione E' stata rilevata una chiave tipo Hardlock: Si puo' procedere con l'installazione /aggiornamento del software APPNAME. Premere il pulsante \"Avanti\". E' stata rilevata una chiave tipo Eutron: Si puo' procedere con l'installazione /aggiornamento del software APPNAME. Premere il pulsante \"Avanti\". E' stato rilevata una chiave remota condivisa in rete con il servizio di gestione autorizzazioni: Si puo' procedere con l'installazione /aggiornamento del software APPNAME. Premere il pulsante \"Avanti\". Non e' stata rilevata alcuna chiave hardware installata sul computer! Per procedere all'installazione della chiave hardware, collegarla al computer e premere il bottone corrispondente alla tipologia della chiave stessa per installarne i driver. Se si utilizza una chiave remota collegata ad un altro computer e condivisa in rete attraverso il servizio gestione di autorizzazioni ");
strBody += wxT("premere il bottone Cerca per attivare la ricerca automatica della chiave remota. Qualora tale ricerca fallisse digitare il nome del computer ");
strBody += wxT("(o l'indirizzo IP) cui e' collegata la chiave di rete e su cui e' installato e attivo il gestore di autorizzazioni. ");
FindWindowById(401)->Enable();
FindWindowById(402)->Enable();
FindWindowById(403)->Enable();
FindWindowById(404)->Enable();
break;
}
SetHTMLText(strTitle, strBody);
return true;
}
void CampoWizardPage4::BuildKey(char* key)
{
for (int i = 0; i < 8; i++)
key[i] = 'A'+ rand()%26;
}
wxString CampoWizardPage4::DecodeString(const wxString& data)
{
char key[8] = "";
BuildKey(key);
char tmp[256];
int i;
for (i = 0; data[i]; i++)
tmp[i] = data[i] - (i < 8 ? key[i] : tmp[i - 8]);
tmp[i] = '\0';
return tmp;
}
int CampoWizardPage4::VersionYear()
{
char ver[32];
GetPrivateProfileString("ba", "Versione", "", ver, sizeof(ver), "../../program/install.ini");
ver[4] = '\0';
return atoi(ver);
}
int CampoWizardPage4::DongleTest()
{
int dongle_type = 0;
int yearKey = 0;
unsigned int serno = 0xFFFF;
wxString strSrvName = GetWizard().GetSrvAuth(); //nome del server di autorizzazioni (se c'e')
if (!strSrvName.IsEmpty())
{
serno = ServerLogin(yearKey, strSrvName);
if (serno != 0xFFFF)
dongle_type = 3; //chiave remota
}
if (serno == 0xFFFF)
{
serno = HardlockLogin(yearKey);
if (serno == 0xFFFF)
{
serno = EutronLogin(yearKey);
if (serno != 0xFFFF)
dongle_type = 2; //chiave eutron
}
else
dongle_type = 1; //chiave hardlock
}
if (serno == 0) // Chiave di sviluppo
return dongle_type;
if (serno == 0xFFFF) // Chiave inesistente o invisibile = Prima installazione o demo
return dongle_type;
const int verYear = VersionYear();
if (yearKey < verYear) // Chiave già programmata con assistenza pagata
{
bool ok = false;
wxFileInputStream file("../dninst.zip");
if (file.IsOk())
{
wxTextInputStream keys(file);
wxString line = keys.ReadLine();
srand(883);
const int ass_year = atoi(DecodeString(line));
if (ass_year > yearKey) // Non devo abbassare l'anno di assistenza!
{
srand(ass_year);
while (!file.Eof())
{
line = keys.ReadLine();
line = DecodeString(line);
unsigned int sn = (unsigned int)atol(line);
if (sn == serno || line[0] == '*')
{
ok = true;
break;
}
}
if (ok)
{
const int n = ass_year%10;
const int y = (ass_year / 1000) * 1000 + (ass_year%1000) /10;
line.Printf("Il contratto di manutenzione %d/%d verrà attivato automaticamente\ndurante l'installazione del software", y, n);
WarningBox(line);
}
else
{
line.Printf("È necessario contattare l'assistenza tecnica\n"
"per l'abilitazione del contratto di manutenzione %d", verYear);
WarningBox(line);
}
}
}
else
{
ErrorBox("Impossibile verificare il contratto di manutenzione");
}
}
return dongle_type;
}
CampoWizardPage4::CampoWizardPage4(wxWizard* parent) : CampoWizardPage(parent)
{
//procedura per la costruzione dei bottoni e delle immagini per l'installazione dei driver di chiave
//"griglia" contenitrice degli oggetti
//griglia per sistemare i campi
wxGridBagSizer* gbsButtSizer = new wxGridBagSizer(VGAP, HGAP);
GetSizer()->Add(gbsButtSizer);
//prima riga della griglia
//Hardlock label
AddLabel(gbsButtSizer, "Installa chiave locale di tipo Hardlock", 0, 0);
//Hardlock image
wxBitmap bmp_HL("../servers/hardlock.gif", wxBITMAP_TYPE_GIF);
wxStaticBitmap* s_bmp_HL = new wxStaticBitmap(this, wxID_ANY, bmp_HL);
gbsButtSizer->Add(s_bmp_HL, wxGBPosition(0, 1));
//bottone Hardlock
wxButton* bHlButton = new wxButton(this, 401, wxT("Hardlock"), wxDefaultPosition, wxSize(64, -1));
gbsButtSizer->Add(bHlButton, wxGBPosition(0, 2), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
//seconda riga della griglia
//Eutron label
AddLabel(gbsButtSizer, "Installa chiave locale di tipo Eutron", 1, 0);
//Eutron image
wxBitmap bmp_EU("../servers/eutron.gif", wxBITMAP_TYPE_GIF);
wxStaticBitmap* s_bmp_EU = new wxStaticBitmap(this, wxID_ANY, bmp_EU);
gbsButtSizer->Add(s_bmp_EU, wxGBPosition(1, 1));
//bottone Eutron
wxButton* bEuButton = new wxButton(this, 402, wxT("Eutron"), wxDefaultPosition, wxSize(64, -1));
gbsButtSizer->Add(bEuButton, wxGBPosition(1, 2), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
//terza riga della griglia
//Server label
AddLabel(gbsButtSizer, "Nome o indirizzo IP del server di autorizzazioni", 2, 0);
//nome Server
wxTextCtrl* tcSrvName = new wxTextCtrl(this, 404, "", wxDefaultPosition, wxSize(128,-1));
gbsButtSizer->Add(tcSrvName, wxGBPosition(2, 1));
//bottone Eutron
wxButton* bSrvButton = new wxButton(this, 403, wxT("Cerca"), wxDefaultPosition, wxSize(64, -1));
gbsButtSizer->Add(bSrvButton, wxGBPosition(2, 2), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
}
/**********************************************************************************************************/
// 5 Scelta tipo installazione
/**********************************************************************************************************/
class CampoWizardPage5 : public CampoWizardPage
{
wxRadioBox* m_pRadioBox;
protected:
virtual bool ForwardValidate();
public:
CampoWizardPage5(wxWizard* parent);
};
bool CampoWizardPage5::ForwardValidate()
{
const unsigned int type = m_pRadioBox->GetSelection();
GetWizard().SetInstallationType(type);
return true;
}
CampoWizardPage5::CampoWizardPage5(wxWizard* parent) : CampoWizardPage(parent)
{
//Istruzioni per l'uso!
wxString strTitle = wxT("Scelta del tipo di installazione");
wxString strBody = wxT(" Standard (scelta consigliata). Installazione su postazione singola, con programmi e dati sul disco locale del computer Installazioni di rete (per utenti esperti) Server: Computer in rete sul quale sono presenti una copia, utilizzata o meno, dei programmi (server programmi) e l’area dati (server dati). ");
strBody += wxT("In una installazione in rete di APPNAME e' necessario sia presente un unica postazione di tipo server, ");
strBody += wxT("e deve essere installata per prima! Client: Computer in rete sul quale e' presente una copia dei programmi ma non l'area dati. ");
strBody += wxT("I client possono essere installati solo dopo l'installazione del server! Digitare nel campo 'Cartella programma' il percorso completo della cartella dove si desidera installare il programma. ");
strBody += wxT("Il percorso di default (consigliato) e' C:\\APPNAME Digitare nel campo 'Cartella Dati' il percorso completo della cartella dove si desidera installare l'area dati. ");
strBody += wxT("Il percorso di default (consigliato) e' C:\\APPNAME\\dati Dati dimostrativi: area dati precompilata per installazioni di tipo dimostrativo del funzionamento del software. ");
strBody += wxT("NON vanno caricati nel caso di una normale installazione! Digitare nel campo 'Cartella programma' il percorso completo della cartella dove si desidera installare il programma. ");
strBody += wxT("Il percorso consigliato e' C:\\APPNAME Digitare nel campo 'Cartella dati' il percorso completo della cartella dove si desidera installare l'area dati. ");
strBody += wxT("Il percorso consigliato e' C:\\APPNAME\\dati Le cartelle del programma e dei dati dovranno essere condivise in modalita' lettura/scrittura agli utenti di sistema e di rete che utilizzeranno il software APPNAME. ");
strBody += wxT("In mancanza di tale condivisione nessun client potra' accedere al server! Gestore autorizzazioni: e' il software che permette di gestire una chiave di protezione hardware multiutenza condivisa in rete. ");
strBody += wxT("Installando tale software e' necessario specificare il computer su cui e' montata la chiave di protezione multiutenza.");
strBody += wxT("Viene di default proposto il computer su cui si sta eseguendo l'installazione di APPNAME (localhost). Gestore dizionari: e' il software che permette di utilizzare APPNAME in lingue diverse dall'italiano. ");
strBody += wxT("Per l'installazione di questo software viene di default proposto il computer su cui si sta eseguendo l'installazione di APPNAME (localhost). Modalita' di esecuzione programmi di gestione Digitare nel campo 'Cartella locale programma' il percorso completo della cartella dove si desidera installare il programma. ");
strBody += wxT("Il percorso consigliato e' C:\\APPNAME Digitare nel campo 'Cartella remota origine programmi' il percorso completo della cartella di rete dove sono i files origine del programma. ");
strBody += wxT("E' la cartella di programmi condivisa dal server precedentemente installato. Digitare nel campo 'Cartella remota dati da utilizzare' il percorso completo della cartella di rete dove sono i dati. ");
strBody += wxT("E' la cartella dei dati condivisa dal server precedentemente installato. Gestore dizionari: e' il computer gestore dei dizionari di APPNAME in lingue diverse dall'italiano. Generalmente e' il computer agente da server di APPNAME in rete. ");
strBody += wxT("Premere il bottone Cerca per attivare la ricerca automatica di tale computer. Qualora tale ricerca fallisse digitare il nome del computer gestore dei dizionari E' possibile creare l'icona di APPNAME sul desktop Cartella programma da aggiornare: ");
strBody += wxT(Bold(_strPrgLocPath) + " Cartella dati in uso: ");
strBody += wxT(Bold(_strDataPath) + " Tipo installazione selezionata: ");
strBody += wxT(Bold(_strInstallType) + " Cartella dove installare il programma: ");
strBody += wxT(Bold(_strPrgLocPath) + " Cartella di origine dei files del programma: ");
strBody += wxT(Bold(_strPrgNetPath) + " Cartella dati da creare: ");
strBody += wxT(Bold(_strDataPath) + " Computer gestore delle autorizzazioni: ");
strBody += wxT(Bold(_strSrvAuth) + " Computer gestore dei dizionari: ");
strBody += wxT(Bold(_strSrvDict) + " Modalita' di esecuzione dei programmi di gestione: ");
if (_iSrvAutostartMode == 0)
strBody += wxT(Bold("Come servizi") + "
");
str += wxT("


");
strBody += wxT("Come servizi: i programmi di gestione vengono eseguiti come servizi di Windows; questa e' la modalita' consigliata ed e' obbligatoria in caso di installazione con Windows 2003
");
strBody += wxT("Nel menu esecuzione automatica: i programmi di gestione vengono eseguiti automaticamente al primo accesso di un utente al server di APPNAME; usare questa modalita' solo nell'impossibilita' di utilizzare la precedente
Installazione area dati dimostrativa
"); if (_bDesktopShortcut) strBody += wxT("Creazione dell' icona sul desktop
"); SetHTMLText(strTitle, strBody); return true; } CampoWizardPage10::CampoWizardPage10(wxWizard* parent) : CampoWizardPage(parent) { } /////////////////////////////////////////////////////////// // CampoWizard /////////////////////////////////////////////////////////// //la dichiarazione della classe e' prima in quanto alcuni suoi metodi sono usati da altre classi scritte piu' su BEGIN_EVENT_TABLE(CampoWizard, wxWizard) EVT_BUTTON(wxID_FORWARD, CampoWizard::OnNext) END_EVENT_TABLE() void CampoWizard::OnNext(wxCommandEvent& e) { CampoWizardPage* p = (CampoWizardPage*)GetCurrentPage(); if (p->ForwardValidate()) e.Skip(); } bool CampoWizard::Run() { return RunWizard(m_pPage[0]); } wxString CampoWizard::Get(wxWindowID id) const { wxWindow* pWnd = FindWindowById(id); return pWnd ? pWnd->GetLabel() : wxEmptyString; } int CampoWizard::GetSelection(wxWindowID id) const { int n = -1; wxWindow* pWnd = FindWindowById(id); if (pWnd) { wxChoice* pList = (wxChoice*)pWnd; n = pList->GetSelection(); } return n; } bool CampoWizard::GetBool(wxWindowID id) const { wxCheckBox* pWnd = (wxCheckBox*)FindWindowById(id); return pWnd != NULL && pWnd->IsChecked(); } void CampoWizard::Set(wxWindowID id, const wxString str) { wxWindow* pWnd = FindWindowById(id); if (pWnd != NULL) pWnd->SetLabel(str); } //lunga litania di metodi per gettare e settare i valori tra le pagine void CampoWizard::SetDestinationPath(const wxString& path) { _strDestinationPath = path; //Se il path di destinazione e' vuoto -> nuova installazione, senno' e' un aggiornamento della installazione.. //..che sta in _strDestinationPath if (_strDestinationPath.IsEmpty()) { wxWizardPageSimple::Chain(m_pPage[3], m_pPage[4]); //installazione nuova } else { wxWizardPageSimple::Chain(m_pPage[3], m_pPage[8]); //aggiornamento } } const wxString& CampoWizard::GetDestinationPath() const { return _strDestinationPath; } void CampoWizard::SetInstallationType(const unsigned int type) { _uInstallationType = type; //in base al tipo di installazione spara l'utente alla pagina corretta switch (_uInstallationType) { case 1: //server wxWizardPageSimple::Chain(m_pPage[4], m_pPage[6]); //manda l'utente alla pagina server wxWizardPageSimple::Chain(m_pPage[6], m_pPage[8]); //dal server alla pagina riassuntiva break; case 2: //client wxWizardPageSimple::Chain(m_pPage[4], m_pPage[7]); //manda l'utente alla pagina client wxWizardPageSimple::Chain(m_pPage[7], m_pPage[8]); //dal client alla pagina riassuntiva break; case 3: //aggiornamento installazione precedente wxWizardPageSimple::Chain(m_pPage[3], m_pPage[8]); //manda l'utente alla pagina riassuntiva break; default: //standard wxWizardPageSimple::Chain(m_pPage[4], m_pPage[5]); //manda l'utente alla pagina standard wxWizardPageSimple::Chain(m_pPage[5], m_pPage[8]); //dalla standard alla pagina riassuntiva break; } } const unsigned int CampoWizard::GetInstallationType() const { return _uInstallationType; } void CampoWizard::SetPrgLocPath(const wxString& strPrgLocPath) { _strPrgLocPath = strPrgLocPath; } const unsigned int CampoWizard::GetDongleType() const { return _uDongleType; } void CampoWizard::SetDongleType(const unsigned int uType) { _uDongleType = uType; } const wxString& CampoWizard::GetPrgLocPath() const { return _strPrgLocPath; } void CampoWizard::SetPrgNetPath(const wxString& strPrgNetPath) { _strPrgNetPath = strPrgNetPath; } const wxString& CampoWizard::GetPrgNetPath() const { return _strPrgNetPath; } void CampoWizard::SetDataPath(const wxString& strDataPath) { _strDataPath = strDataPath; } const wxString& CampoWizard::GetDataPath() const { return _strDataPath; } void CampoWizard::SetInstUseAuth(const bool bInstUseAuth) { _bInstUseAuth = bInstUseAuth; } const bool CampoWizard::GetInstUseAuth() const { return _bInstUseAuth; } void CampoWizard::SetSrvAuth(const wxString& strSrvAuth) { _strSrvAuth = strSrvAuth; } const wxString& CampoWizard::GetSrvAuth() const { return _strSrvAuth; } void CampoWizard::SetInstUseDict(const bool bInstUseDict) { _bInstUseDict = bInstUseDict; } const bool CampoWizard::GetInstUseDict() const { return _bInstUseDict; } void CampoWizard::SetSrvDict(const wxString& strSrvDict) { _strSrvDict = strSrvDict; } const wxString& CampoWizard::GetSrvDict() const { return _strSrvDict; } void CampoWizard::SetSrvAutostartMode(const int iSrvAutostartMode) { _iSrvAutostartMode = iSrvAutostartMode; } const int CampoWizard::GetSrvAutostartMode() const { return _iSrvAutostartMode; } void CampoWizard::SetInstDemoData(const bool bInstDemoData) { _bInstDemoData = bInstDemoData; } const bool CampoWizard::GetInstDemoData() const { return _bInstDemoData; } void CampoWizard::SetDesktopShortcut(const bool bDesktopShortcut) { _bDesktopShortcut = bDesktopShortcut; } const bool CampoWizard::GetDesktopShortcut() const { return _bDesktopShortcut; } //...fine litania metodi di passaggio valori tra le finestre CampoWizard::CampoWizard(wxWindow* pParent) { //resettatore dei booleans (che senno' prendono valore casuale ad ogni esecuzione) _bInstDemoData = false; //installa dati dimostrativi _bInstUseAuth = false; //installa/usa server authoriz _bInstUseDict = false; //installa/usa server diction _bDesktopShortcut = false; //creazione link sul desktop wxBitmap bitmap; wxString strName = wxT("logo.gif"); bitmap.LoadFile(strName, wxBITMAP_TYPE_GIF); Create(pParent, wxID_ANY, APPNAME, bitmap); m_pPage[0] = new CampoWizardPage1(this); //benvenuto con logo m_pPage[1] = new CampoWizardPage2(this); //licenza m_pPage[2] = new CampoWizardPage3(this); //scelta aggiornamento/tipo installazione m_pPage[3] = new CampoWizardPage4(this); //test ed installazione chiavi m_pPage[4] = new CampoWizardPage5(this); //selezione tipo installazione m_pPage[5] = new CampoWizardPage6(this); //installazione standard m_pPage[6] = new CampoWizardPage7(this); //installazione server m_pPage[7] = new CampoWizardPage8(this); //installazione client m_pPage[8] = new CampoWizardPage9(this); //creazione icona sul desktop e in start/programmi/campo m_pPage[9] = new CampoWizardPage10(this); //riassuntino installazione for (int p = 1; p < m_nPages; p++) wxWizardPageSimple::Chain(m_pPage[p-1], m_pPage[p]); GetPageAreaSizer()->Add(m_pPage[0]); //bottoni di navigazione Set(wxID_FORWARD, "Avanti"); Set(wxID_BACKWARD, "Indietro"); Set(wxID_CANCEL, "Annulla"); } /////////////////////////////////////////////////////////// // CampoFrame /////////////////////////////////////////////////////////// class CampoFrame : public wxFrame { protected: DECLARE_EVENT_TABLE(); virtual void OnErase(wxEraseEvent& e); public: CampoFrame(); }; BEGIN_EVENT_TABLE(CampoFrame, wxFrame) EVT_ERASE_BACKGROUND(CampoFrame::OnErase) END_EVENT_TABLE() void CampoFrame::OnErase(wxEraseEvent& e) { //preparazione background wxDC& dc = *e.GetDC(); const wxRect rect = GetClientSize(); wxColour c0 = wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT); wxColour c1 = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE); wxColour c2 = wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW); wxRect rect1 = rect; rect1.SetBottom(rect.GetBottom() / 2); dc.GradientFillLinear(rect1, c0, c1, wxSOUTH); wxRect rect2 = rect; rect2.SetTop(rect.GetBottom() / 2); dc.GradientFillLinear(rect2, c1, c2, wxDOWN); const int nHeight = rect.GetHeight()/8; wxFont* pFont = wxTheFontList->FindOrCreateFont(nHeight, wxFONTFAMILY_SWISS, wxFONTSTYLE_ITALIC, wxFONTWEIGHT_BOLD); dc.SetFont(*pFont); dc.SetBackgroundMode(wxTRANSPARENT); const int k = nHeight / 16 + 1; dc.SetTextForeground(c2); dc.DrawText(APPNAME, k, k); dc.SetTextForeground(c1); dc.DrawText(APPNAME, k/2, k/2); int w, h; const wxString strSetup = wxT("Setup"); dc.GetTextExtent(strSetup, &w, &h); dc.SetTextForeground(c2); dc.DrawText(strSetup, rect.GetRight()-w-k/2, rect.GetHeight()-h-k/2); dc.SetTextForeground(c1); dc.DrawText(strSetup, rect.GetRight()-w-k, rect.GetHeight()-h-k); } CampoFrame::CampoFrame() : wxFrame(NULL, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0) { ShowFullScreen(true); } /////////////////////////////////////////////////////////// // CampoSetup /////////////////////////////////////////////////////////// //classe principale, ovvero applicazione class CampoSetup : public wxApp { CampoFrame* m_pMainFrame; wxLocale m_locale; wxString m_strSetupPath; CampoWizard* m_pWizard; private: bool WriteRegistryKey(HKEY hBaseKey, const wxString strKey, const wxString& strValue) const; wxString ReadRegistryKey(HKEY hBaseKey, const wxString strKey) const; wxString GetFolderPath(unsigned int uPathID) const; protected: DECLARE_EVENT_TABLE() void OnTimer(wxTimerEvent& e); bool CreateIcon(unsigned int csidl, const wxFileName& strExeFile) const; bool CreateAutostartMode(const int iSrvAutostartMode, const wxString& strPath); void AssociateExtension(const wxFileName& strExeFile, const wxString strExt); wxString ReadRootRegistryKey(const wxString strKey) const; wxString ReadLocalMachineRegistryKey(const wxString strKey) const; bool WriteRootRegistryKey(const wxString strKey, const wxString& strValue) const; bool WriteLocalMachineRegistryKey(const wxString strKey, const wxString& strValue) const; void CheckAndMakeDir(const wxString& strDir, const wxString& strMsg) const; bool UnzipFile(const char* strZipFile, const char* strDestdir) const; size_t GetZipList(const char* strZipFile, wxArrayString& aFiles) const; const wxString GetSourceDir(const wxString strDirName) const; void UnzipSystem(const wxString& strPrgLocPath) const; public: virtual bool OnInit(); }; IMPLEMENT_APP(CampoSetup) BEGIN_EVENT_TABLE(CampoSetup, wxApp) EVT_TIMER(883, OnTimer) END_EVENT_TABLE() //metodi di lettura/scrittura registry di windows (fantastici!) wxString CampoSetup::ReadRegistryKey(HKEY hBaseKey, const wxString strKey) const { wxString strValue; HKEY hKey = NULL; wxString strPath, strName; wxFileName::SplitPath(strKey, &strPath, &strName, NULL); bool ok = ::RegOpenKeyEx(hBaseKey, strPath, 0, KEY_READ, &hKey) == ERROR_SUCCESS; if (ok) { BYTE buff[512]; DWORD type = REG_SZ; DWORD dw = sizeof(buff); ok = ::RegQueryValueEx(hKey, strName, NULL, &type, buff, &dw) == ERROR_SUCCESS; if (ok) strValue = buff; ::RegCloseKey(hKey); } return strValue; } wxString CampoSetup::ReadRootRegistryKey(const wxString strKey) const { return ReadRegistryKey(HKEY_CLASSES_ROOT, strKey); } wxString CampoSetup::ReadLocalMachineRegistryKey(const wxString strKey) const { return ReadRegistryKey(HKEY_LOCAL_MACHINE, strKey); } bool CampoSetup::WriteRegistryKey(HKEY hBaseKey, const wxString strKey, const wxString& strValue) const { HKEY hKey = NULL; DWORD dw = 0; //splitta la stringa in path e valore wxString strPath, strName; wxFileName::SplitPath(strKey, &strPath, &strName, NULL); bool ok = ::RegCreateKeyEx(hBaseKey, strPath, 0, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, &hKey, &dw) == ERROR_SUCCESS; if (ok) { ok = ::RegSetValueEx(hKey, strName, 0, REG_SZ, (BYTE*)(const wxChar*)strValue, DWORD(2*strValue.Len()+2)) == ERROR_SUCCESS; ::RegCloseKey(hKey); } return ok; } bool CampoSetup::WriteRootRegistryKey(const wxString strKey, const wxString& strValue) const { return WriteRegistryKey(HKEY_CLASSES_ROOT, strKey, strValue); } bool CampoSetup::WriteLocalMachineRegistryKey(const wxString strKey, const wxString& strValue) const { return WriteRegistryKey(HKEY_LOCAL_MACHINE, strKey, strValue); } wxString CampoSetup::GetFolderPath(unsigned int uPathID) const { TCHAR szPath[MAX_PATH] = wxT(""); HRESULT hres = ::SHGetFolderPath(NULL, uPathID, NULL, SHGFP_TYPE_CURRENT, szPath); return szPath; } void CampoSetup::AssociateExtension(const wxFileName& strExeFile, const wxString strExt) { // Register icon and application WriteRootRegistryKey(strExt, APPNAME); wxString str = strExeFile.GetFullPath(); str += wxT(",0"); WriteRootRegistryKey(wxT("Campo\\DefaultIcon"), str); str = strExeFile.GetFullPath(); str += wxT(" \"%1\""); WriteRootRegistryKey(wxT("Campo\\shell\\open\\command"), str); } bool CampoSetup::CreateAutostartMode(const int iSrvAutostartMode, const wxString& strPath) { //creazione dei filenames e dei path necessari in giro per la funzione //filename (con path quindi) di Lurch.exe wxFileName strExe(strPath, wxT("lurch.exe")); strExe.AppendDir("servers"); //stringa path della cartella Servers in base alle scelte dell'utente const wxString strSrvPath = strPath + "\\servers"; switch (iSrvAutostartMode) { //esecuzione server come servizi (magia!) case 0: { //cerca se non esiste per caso gia' da una precedente installazione.. //..non serve piu' a un cazzo ma si e' tenuto come prova in debug di lettura del registry! wxString strValue = ReadLocalMachineRegistryKey("SYSTEM\\CurrentControlSet\\Services\\Lurch\\Parameters\\Application"); //elimina un eventuale servizio precedente (senno' col cavolo che lo riesce a modificare!) //utilizza il programma instsrv.exe dentro la cartella servers installata wxString strRemove = strSrvPath + "\\instsrv Lurch REMOVE"; const long lRemove = wxExecute(strRemove, wxEXEC_SYNC); //aggiunge la voce ai servizi di windows (dentro strumenti di amministrazione) //utilizza i programmi instrv.exe e srvany.exe dentro la cartella servers installata wxString strCreateService = strSrvPath + "\\instsrv Lurch "; strCreateService += strSrvPath; strCreateService += "\\srvany.exe"; //esegue il programma di installazione servizi di Windows creando la voce const long lExec = wxExecute(strCreateService, wxEXEC_SYNC); if (lExec >= 0) { //crea le voci nel registry di windows WriteLocalMachineRegistryKey("SYSTEM\\CurrentControlSet\\Services\\Lurch\\Parameters\\Application", strExe.GetFullPath()); wxString strExecService = GetFolderPath(CSIDL_SYSTEM); strExecService += "\\NET START Lurch"; //avvia il servizio const long lExecLurch = wxExecute(strExecService, wxEXEC_SYNC); if (lExecLurch < 0) WarningBox("Impossibile eseguire il servizio del gestore applicazioni.\nLanciarlo manualmente dagli strumenti di amministrazione nel pannello di controllo!"); } else WarningBox("Impossibile registrare il servizio per l'esecuzione automatica del gestore applicazioni.\nSelezionare una diversa modalita' di esecuzione!"); } break; //link nella cartella esecuzione automatica case 1: { CreateIcon(CSIDL_COMMON_STARTUP, strExe); } break; default: break; } return true; } bool CampoSetup::CreateIcon(unsigned int csidl, const wxFileName& strExeFile) const { //csidl = CSIDL_COMMON_DESKTOPDIRECTORY = desktop //csidl = CSIDL_COMMON_STARTUP = all users esecuzione automatica wxString strDesktopPath = GetFolderPath(csidl); if (!strDesktopPath.IsEmpty()) { CoInitialize(NULL); // Get a pointer to the IShellLink interface. IShellLink* psl; HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&psl); if (SUCCEEDED(hres)) { IPersistFile* ppf; // Set the path to the shortcut target and add the description. psl->SetPath(strExeFile.GetFullPath()); psl->SetWorkingDirectory(strExeFile.GetPath()); psl->SetDescription(APPNAME); // Query IShellLink for the IPersistFile interface for saving the // shortcut in persistent storage. hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); if (SUCCEEDED(hres)) { wxFileName strLnk; if (csidl == CSIDL_COMMON_STARTUP) strLnk.Assign(strDesktopPath, wxT("Lurch.lnk")); else strLnk.Assign(strDesktopPath, wxT("Campo.lnk")); // Save the link by calling IPersistFile::Save. wxString stringa = strLnk.GetFullPath(); wchar_t buff[_MAX_PATH]; memset(buff, 0, sizeof(buff)); wxConvLocal.MB2WC(buff, stringa, stringa.Len()); hres = ppf->Save(buff, true); ppf->Release(); } psl->Release(); } CoUninitialize(); } return true; } void CampoSetup::CheckAndMakeDir(const wxString& strDir, const wxString& strMsg) const { 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)) { 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; } } } size_t CampoSetup::GetZipList(const char* strZipFile, wxArrayString& aFiles) const { 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 CampoSetup::UnzipFile(const char* strZipFile, const char* strDestDir) const { wxArrayString aFiles; const size_t files = GetZipList(strZipFile, aFiles); wxProgressDialog pi("Unzip", "", (int)files, NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); 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; if (!::wxDirExists(strOutDir)) ::wxMkdir(strOutDir); } 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); } } return files > 0; } static int PatchCompare(const wxString& first, const wxString& second) { const wxFileName fn1(first); const wxFileName fn2(second); const wxString strName1 = fn1.GetName().Lower(); const wxString strName2 = fn2.GetName().Lower(); if (strName1 == "syinst1") return -1; if (strName2 == "syinst1") return 1; return strName1.CompareTo(strName2); } const wxString CampoSetup::GetSourceDir(const wxString strDirName) const { wxFileName strSourcePath(m_strSetupPath, "pippo.txt"); strSourcePath.AppendDir(".."); strSourcePath.AppendDir(".."); strSourcePath.AppendDir(strDirName); strSourcePath.MakeAbsolute(); const wxString strSrc = strSourcePath.GetPath(); return strSrc; } void CampoSetup::UnzipSystem(const wxString& strPrgLocPath) const { wxArrayString asFilesList; const wxString strSrc = GetSourceDir("program"); //..contando anche quanti sono e memorizzandoli in un array asFileList const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asFilesList, "sy*.zip"); if (uFilesToCopy > 0) { //ordina le patch per numero crescente ma mette davanti a tutte il pacco (sysinst1) asFilesList.Sort(PatchCompare); for (size_t i = 0; i < uFilesToCopy; i++) { UnzipFile(asFilesList[i] , strPrgLocPath); } //aggiorna l'install.ini in base al numero di patch e versione dell'ultimo file zip di sistema //ci vuole un giro allucinogeno per trasformare il .zip in .ini e togliere quel cazzo di 1 in fondo wxFileName strLastFile(asFilesList[uFilesToCopy - 1]); //zip con path completo wxString strWrk = strLastFile.GetName(); strWrk.Truncate(strWrk.Len() - 1); strLastFile.SetName(strWrk); strLastFile.SetExt("ini"); strWrk = strLastFile.GetFullPath(); //adesso che ha trovato quello sporco ultimo .ini prende versione e patch e le copia nell'install.ini.. //..nella dir dei programmi; lo fa paragrafo x paragrafo ([sy],[sy1]..) //potrebbe sembrare assurdo un for, ma e' per futuri sottomoduli con numero > 1 for (int j = 0; j < 2; j++) { wxString strParagraph = "sy"; if (j > 0) strParagraph << j; CampoIniFile SyLastPatch(strWrk, strParagraph); const wxString strVersion = SyLastPatch.Get("Versione"); const wxString strPatch = SyLastPatch.Get("Patch"); CampoIniFile InstallIni(strPrgLocPath + "/install.ini", strParagraph); InstallIni.Set("Versione", strVersion); InstallIni.Set("Patch", strPatch); } } } //metodo principale dell'applicazione che gestisce l'ordine degli eventi nella installazione vera e propria void CampoSetup::OnTimer(wxTimerEvent& WXUNUSED(e)) { m_pWizard = new CampoWizard(m_pMainFrame); wxFileName strPath = argv[0]; strPath.SetCwd(); //path del programma setup.exe in esecuzione; serve in seguito in quanto alcuni metodi (tipo la GetAllFiles).. //..fanno perdere questo path m_strSetupPath = strPath.GetPath(); if (m_pWizard->Run()) { // 1) RACCOLTA PARAMETRI GENERALI INSTALLAZIONE (tipo,path,cartelle,servers,...) //------------------------------------------------------------------------------ //tipo di installazione/aggiornamento const unsigned int uInstallationType = m_pWizard->GetInstallationType(); const bool bNewInstallation = uInstallationType < 3; //installazione servers? solo per server di campo const bool bInstallLurch = uInstallationType == 1 && (m_pWizard->GetInstUseAuth() || m_pWizard->GetInstUseDict()); //uso servers? sarebbe solo per i client ma lo teniamo buono per tutti const bool bUseLurch = uInstallationType != 1 && (!m_pWizard->GetSrvAuth().IsEmpty() || !m_pWizard->GetSrvDict().IsEmpty()); //installazione datidemo? (oddio speriamo di no!; comunque vale solo per installazione standard) const bool bInstallDemoData = uInstallationType == 0 && m_pWizard->GetInstDemoData(); //cartelle selezionate dall'utente const wxString& strPrgLocPath = m_pWizard->GetPrgLocPath(); const wxString& strDataPath = m_pWizard->GetDataPath(); //se nuova installazione deve anche creare la directory di destinazione if (bNewInstallation) { //creazione della directory dei programmi (compreso l'intero albero directory) CheckAndMakeDir(strPrgLocPath, "programmi"); //creazione della directory dei dati (compreso l'intero albero directory) CheckAndMakeDir(strDataPath, "dati"); } // 2) COPIA DEI FILES DI INSTALLAZIONE DALLA CARTELLA CAMPO (E SUBDIRS) (SU CD) ALLA CARTELLA DESTINAZIONE //-------------------------------------------------------------------------------------------------------- //copia del contenuto della cartella campo nella cartella di destinazione (installaz/aggiornam) //per prima cosa cerca la cartella dei files sorgente... wxArrayString asFilesList; wxFileName strSourcePath(m_strSetupPath, "*.*"); strSourcePath.AppendDir(".."); strSourcePath.MakeAbsolute(); //stringa inutile al programma ma decisiva per il programmatore const wxString strSrc = strSourcePath.GetPath(); //..contando anche quanti sono e memorizzandoli in un array asFileList const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asFilesList); //per ogni file da copiare controlla i path sorgente e destinazione(problema con sottodirectory tipo dati) wxString strFileCurr; const size_t nPathLenght = strSourcePath.GetPath().Len(); //progress bar wxProgressDialog pi("Installazione Dati e Programmi di base...", "", (int)uFilesToCopy, NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); for (size_t i = 0; i < uFilesToCopy; i++) { //aggiorna la progind if (!pi.Update((int)i, asFilesList[i])) break; //files dei dati standard! solo in caso di nuova installazione!! if (asFilesList[i].Lower().Find("\\dati\\") > 0) { //i DATI NON VANNO MAI installati in caso di aggiornamento!!! //e nemmeno in caso si scelga di installare i dati demo (senno' sporca la dir dati e i datidemo non si installano) //Ricordare che c'e' gia' stato il controllo nella Forward della pagina di selezione, quindi la cartella.. //..di destinazione e' comunque vuota if (bNewInstallation && !bInstallDemoData) { strFileCurr = strDataPath; strFileCurr += asFilesList[i].Mid(nPathLenght + 5); } } else { //che fare con i servers? copiare la directory..potrebbe servire if (asFilesList[i].Lower().Find("\\servers\\") > 0) { if (bInstallLurch) { strFileCurr = strPrgLocPath; strFileCurr += "\\servers"; strFileCurr += asFilesList[i].Mid(nPathLenght + 8); } } else //files dei programmi { strFileCurr = strPrgLocPath; strFileCurr += asFilesList[i].Mid(nPathLenght); } } //copia i files nella cartella di destinazione (programmi,dati,cazzi e mazzi);se il nome del file.. //..di destinazione e' vuoto significa che non lo deve copiare!! (es. dati in aggiornamento) if (!strFileCurr.IsEmpty()) { strFileCurr.MakeLower(); //minuscolizzazione di sicurezza const wxFileName strFileName(strFileCurr); //i files .ini vanno trattati con i guanti (se esistono gia' non vanno copiati!!!) if (strFileName.GetExt() == "ini") { const wxString strName = strFileName.GetName(); //campo.ini e install.ini vanno lasciati stare se esistono (aggiornamento)!!! if ((strName == "campo" || strName == "install") && strFileName.FileExists()) continue; } //eventuali sottodirectory le crea (solo se hanno un nome) const wxString strDir = strFileName.GetPath(); if (!strDir.IsEmpty() && !wxDirExists(strDir)) wxMkdir(strDir); if(!wxCopyFile(asFilesList[i], strFileCurr)) { wxString strErr = "Impossibile copiare il file "; strErr += asFilesList[i]; strErr += " in "; strErr += strFileCurr; strErr += "\nInstallazione interrotta!"; ErrorBox(strErr); break; } } //if (!strFileCurr.IsEmpty().. } //for(size_t... // 3) INSTALLAZIONE DATI DEMO //--------------------------- //installazione dei dati dimostrativi (che schifo!).Non si puo' fare in aggiornamento! if (bInstallDemoData && uInstallationType < 3) { //trova la cartella datidemo da copiare wxArrayString asDataList; const wxString strSrc = GetSourceDir("datidemo"); //conta i files da copiare e si lancia nell'operazione di copiatura... //Vale quanto detto per l'installazione dell'area dati const size_t uFilesToCopy = wxDir::GetAllFiles(strSrc, &asDataList); wxString strFileCurr; const size_t nPathLenght = strSrc.Len(); wxProgressDialog pi("Installazione Dati Demo...", "", (int)uFilesToCopy, NULL, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT); for (size_t i = 0; i < uFilesToCopy; i++) { if (!pi.Update((int)i, asDataList[i])) break; asDataList[i].Lower(); strFileCurr = strDataPath; strFileCurr += asDataList[i].Mid(nPathLenght); if (!strFileCurr.IsEmpty()) { strFileCurr.MakeLower(); const wxFileName strFileName(strFileCurr); const wxString strDir = strFileName.GetPath(); if (!strDir.IsEmpty() && !wxDirExists(strDir)) wxMkdir(strDir); if(!wxCopyFile(asDataList[i], strFileCurr)) { wxString strErr = "Impossibile copiare il file "; strErr += asDataList[i]; strErr += " in "; strErr += strFileCurr; strErr += "\nInstallazione interrotta!"; ErrorBox(strErr); break; } } //if (!strFileCurr.IsEmpty().. } //for (size_t i = 0... } //if(bInstallDemoData... // 4) COMPILAZIONE CAMPO.INI CON CONFIGURAZIONE NUOVA INSTALLAZIONE //----------------------------------------------------------------- //adesso deve compilare il campo.ini se nuova installazione.. if (bNewInstallation) { { //parentesi necessaria per la scrittura immediata (non cancellare! serve per debug) //paragrafo [Main] CampoIniFile CampoIniMain(strPrgLocPath + "/campo.ini", "Main"); const unsigned int uDongleType = m_pWizard->GetDongleType(); CampoIniMain.Set("Donglehw", uDongleType); CampoIniMain.Set("Study", strDataPath); CampoIniMain.Set("Firm", "com"); //client o non client? if (uInstallationType == 2) //client { CampoIniMain.Set("TestDatabase", "N"); CampoIniMain.Set("TestPrograms", "X"); } else //altri (standard,server) { CampoIniMain.Set("TestDatabase", "X"); CampoIniMain.Set("TestPrograms", "N"); } } //paragrafo [Server] if (bInstallLurch || bUseLurch) { CampoIniFile CampoIniSrv(strPrgLocPath + "/campo.ini", "Server"); CampoIniSrv.Set("Dongle", m_pWizard->GetSrvAuth()); CampoIniSrv.Set("Dictionary", m_pWizard->GetSrvDict()); } } //if(bNewInstallation... // 5) COMPILAZIONE\AGGIORNAMENTO INSTALL.INI CON DISKPATH //------------------------------------------------------- //..e modificare comunque l'install.ini aggiornando eventualmente l'origine dei programmi //parentesi necessaria per la scrittura immediata (non cancellare! serve per debug) { CampoIniFile CampoInstall(strPrgLocPath + "/install.ini", "Main"); if (uInstallationType == 2) //client: directory origine sul server CampoInstall.Set("DiskPath", m_pWizard->GetPrgNetPath()); else //e' il path assoluto dell'install.ini che sta in 'program' (es. D:\program) { wxFileName strSourcePath(m_strSetupPath + "/install.ini"); const wxString strSrc = GetSourceDir("program"); CampoInstall.Set("DiskPath", strSrc); } } // 6) CREAZIONE AUTOSTART DEI SERVERS (SE CI SONO) //------------------------------------------------ //solo se sta installando campo in postazione server e deve installare un gestore di servizi.. //..avvia la procedura della creazione dell'autostart(un casino) if (bInstallLurch) { const int iSrvAutostartMode = m_pWizard->GetSrvAutostartMode(); CreateAutostartMode(iSrvAutostartMode, strPrgLocPath); } // 7) AGGIORNAMENTO DEL MODULO SY CON EVENTUALI PATCH PRESENTI IN PROGRAM DEL CD E AGGIORNAMENTO INSTALL.INI //---------------------------------------------------------------------------------------------------------- //procede poi al caricamento delle patch eventuali di sistema all'interno della dir 'program' e al.. //..conseguente riaggiornamento del livello versione/patch del SY in install.ini UnzipSystem(strPrgLocPath); // 8) CREAZIONE DELL'ICONA SUL DESKTOP //------------------------------------ const wxFileName strExe(strPrgLocPath, wxT("ba0.exe")); const bool bDesktopShortcut = m_pWizard->GetDesktopShortcut(); if (bDesktopShortcut) CreateIcon(CSIDL_COMMON_DESKTOPDIRECTORY, strExe); // 9) AGGIORNAMENTO CAMPO.STP //--------------------------- if (bNewInstallation) { //deve aggiungere la nuova installazione al campo.stp for (int i = 1;; i++) { wxString strGroup; strGroup << i; CampoIniFile CampoStp("C:\\campo.stp", strGroup); wxString strPath = CampoStp.Get("Program"); if (strPath.IsEmpty()) { CampoStp.Set("Program", strPrgLocPath); break; } } } // 10) CHIUDE IL SETUP LANCIANDO BA1 -6 PER INSTALLAZIONE MODULI //------------------------------------------------------------- //lanciare ba1.exe -6 in uscita (non va qui! e' solo per ricordarsi di farlo!) wxSetWorkingDirectory(strPrgLocPath); wxExecute("ba1 -6 /uADMIN"); } //if (m_pWizard->Run())... m_pWizard->Destroy(); //finestrina x chiudere a mano il programma (sconsigliata causa lancio ba1.exe) // ::wxMessageBox(wxT("Installazione terminata"), APPNAME, wxOK | wxICON_INFORMATION); m_pMainFrame->Destroy(); } bool CampoSetup::OnInit() { wxInitAllImageHandlers(); m_locale.Init(); m_pMainFrame = new CampoFrame; SetTopWindow(m_pMainFrame); wxTimerEvent e(883); AddPendingEvent(e); return true; }