~ubuntu-branches/ubuntu/precise/boinc/precise

« back to all changes in this revision

Viewing changes to clientgui/BOINCGUIApp.cpp

Tags: 6.12.8+dfsg-1
* New upstream release.
* Simplified debian/rules

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Berkeley Open Infrastructure for Network Computing
2
 
// http://boinc.berkeley.edu
3
 
// Copyright (C) 2005 University of California
4
 
//
5
 
// This is free software; you can redistribute it and/or
6
 
// modify it under the terms of the GNU Lesser General Public
7
 
// License as published by the Free Software Foundation;
8
 
// either version 2.1 of the License, or (at your option) any later version.
9
 
//
10
 
// This software is distributed in the hope that it will be useful,
11
 
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 
// See the GNU Lesser General Public License for more details.
14
 
//
15
 
// To view the GNU Lesser General Public License visit
16
 
// http://www.gnu.org/copyleft/lesser.html
17
 
// or write to the Free Software Foundation, Inc.,
18
 
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 
20
 
#if defined(__GNUG__) && !defined(__APPLE__)
21
 
#pragma implementation "BOINCGUIApp.h"
22
 
#endif
23
 
 
24
 
#ifdef __WXMAC__
25
 
#include <Carbon/Carbon.h>
26
 
#include "filesys.h"
27
 
#include "util.h"
28
 
#if (defined(SANDBOX) && defined(_DEBUG))
29
 
#include "SetupSecurity.h"
30
 
#endif
31
 
#include "sandbox.h"
32
 
#endif
33
 
 
34
 
#include "stdwx.h"
35
 
#include "diagnostics.h"
36
 
#include "network.h"
37
 
#include "util.h"
38
 
#include "mfile.h"
39
 
#include "miofile.h"
40
 
#include "parse.h"
41
 
#include "Events.h"
42
 
#include "common/wxFlatNotebook.h"
43
 
#include "LogBOINC.h"
44
 
#include "BOINCGUIApp.h"
45
 
#include "SkinManager.h"
46
 
#include "MainDocument.h"
47
 
#include "BOINCClientManager.h"
48
 
#include "BOINCTaskBar.h"
49
 
#include "BOINCBaseFrame.h"
50
 
#include "AdvancedFrame.h"
51
 
#include "sg_ImageLoader.h"
52
 
#include "sg_StatImageLoader.h"
53
 
#include "sg_BoincSimpleGUI.h"
54
 
#include "DlgExitMessage.h"
55
 
 
56
 
static bool s_bSkipExitConfirmation = false;
57
 
 
58
 
#ifdef __WXMSW__
59
 
EXTERN_C BOOL  ClientLibraryStartup();
60
 
EXTERN_C BOOL  IdleTrackerAttach();
61
 
EXTERN_C void  IdleTrackerDetach();
62
 
EXTERN_C void  ClientLibraryShutdown();
63
 
EXTERN_C DWORD BOINCGetIdleTickCount();
64
 
#endif
65
 
 
66
 
 
67
 
IMPLEMENT_APP(CBOINCGUIApp)
68
 
IMPLEMENT_DYNAMIC_CLASS(CBOINCGUIApp, wxApp)
69
 
 
70
 
 
71
 
bool CBOINCGUIApp::OnInit() {
72
 
 
73
 
    // Setup variables with default values
74
 
    m_strBOINCArguments = wxEmptyString;
75
 
    m_strBOINCMGRRootDirectory = wxEmptyString;
76
 
    m_strBOINCMGRDataDirectory = wxEmptyString;
77
 
    m_pLocale = NULL;
78
 
    m_pSkinManager = NULL;
79
 
    m_pFrame = NULL;
80
 
    m_pDocument = NULL;
81
 
    m_pTaskBarIcon = NULL;
82
 
#ifdef __WXMAC__
83
 
    m_pMacSystemMenu = NULL;
84
 
    printf("Using %s.\n", wxVERSION_STRING);    // For debugging
85
 
#endif
86
 
    m_bGUIVisible = true;
87
 
    m_strDefaultWindowStation = wxEmptyString;
88
 
    m_strDefaultDesktop = wxEmptyString;
89
 
    m_strDefaultDisplay = wxEmptyString;
90
 
    m_bBOINCMGRAutoStarted = false;
91
 
    m_iBOINCMGRDisableAutoStart = 0;
92
 
    m_iShutdownCoreClient = 0;
93
 
    m_iDisplayExitDialog = 1;
94
 
    m_iGUISelected = BOINC_SIMPLEGUI;
95
 
#ifdef __WXMSW__
96
 
    m_hClientLibraryDll = NULL;
97
 
#endif
98
 
 
99
 
#if (defined(SANDBOX) || defined(__WXMAC__))
100
 
    int errCode = 0;
101
 
#endif
102
 
 
103
 
#ifdef SANDBOX
104
 
    g_use_sandbox = true;
105
 
#else
106
 
    g_use_sandbox = false;
107
 
#endif
108
 
 
109
 
    // Initialize local variables
110
 
    int      iSelectedLanguage = 0;
111
 
    wxString strDesiredSkinName = wxEmptyString;
112
 
    wxString strDialogMessage = wxEmptyString;
113
 
 
114
 
    // Commandline parsing is done in wxApp::OnInit()
115
 
    if (!wxApp::OnInit()) {
116
 
        return false;
117
 
    }
118
 
    
119
 
#ifndef _WIN32
120
 
    if (g_use_sandbox)
121
 
        umask (2);  // Set file creation mask to be writable by both user and group
122
 
                    // Our umask will be inherited by all our child processes
123
 
#endif
124
 
 
125
 
    // Setup application and company information
126
 
    SetAppName(wxT("BOINC Manager"));
127
 
    SetVendorName(wxT("Space Sciences Laboratory, U.C. Berkeley"));
128
 
 
129
 
    // Initialize the configuration storage module
130
 
    m_pConfig = new wxConfig(GetAppName());
131
 
    wxConfigBase::Set(m_pConfig);
132
 
    wxASSERT(m_pConfig);
133
 
 
134
 
    m_pConfig->SetPath(wxT("/"));
135
 
 
136
 
    // Restore Application State
137
 
    m_pConfig->Read(wxT("AutomaticallyShutdownClient"), &m_iShutdownCoreClient, 0L);
138
 
    m_pConfig->Read(wxT("DisplayShutdownClientDialog"), &m_iDisplayExitDialog, 1L);
139
 
    m_pConfig->Read(wxT("DisableAutoStart"), &m_iBOINCMGRDisableAutoStart, 0L);
140
 
    m_pConfig->Read(wxT("Language"), &iSelectedLanguage, 0L);
141
 
    m_pConfig->Read(wxT("GUISelection"), &m_iGUISelected, BOINC_SIMPLEGUI);
142
 
 
143
 
 
144
 
    // Should we abort the BOINC Manager startup process?
145
 
    if (m_bBOINCMGRAutoStarted && m_iBOINCMGRDisableAutoStart) {
146
 
        return false;
147
 
    }
148
 
 
149
 
#ifdef __WXMSW__
150
 
 
151
 
    //
152
 
    // Determine BOINCMgr Data Directory
153
 
    //
154
 
        LONG    lReturnValue;
155
 
        HKEY    hkSetupHive;
156
 
    LPTSTR  lpszRegistryValue = NULL;
157
 
        DWORD   dwSize = 0;
158
 
 
159
 
    // change the current directory to the boinc data directory if it exists
160
 
        lReturnValue = RegOpenKeyEx(
161
 
        HKEY_LOCAL_MACHINE, 
162
 
        _T("SOFTWARE\\Space Sciences Laboratory, U.C. Berkeley\\BOINC Setup"),
163
 
                0, 
164
 
        KEY_READ,
165
 
        &hkSetupHive
166
 
    );
167
 
    if (lReturnValue == ERROR_SUCCESS) {
168
 
        // How large does our buffer need to be?
169
 
        lReturnValue = RegQueryValueEx(
170
 
            hkSetupHive,
171
 
            _T("DATADIR"),
172
 
            NULL,
173
 
            NULL,
174
 
            NULL,
175
 
            &dwSize
176
 
        );
177
 
        if (lReturnValue != ERROR_FILE_NOT_FOUND) {
178
 
            // Allocate the buffer space.
179
 
            lpszRegistryValue = (LPTSTR) malloc(dwSize);
180
 
            (*lpszRegistryValue) = NULL;
181
 
 
182
 
            // Now get the data
183
 
            lReturnValue = RegQueryValueEx( 
184
 
                hkSetupHive,
185
 
                _T("DATADIR"),
186
 
                NULL,
187
 
                NULL,
188
 
                (LPBYTE)lpszRegistryValue,
189
 
                &dwSize
190
 
            );
191
 
 
192
 
            SetCurrentDirectory(lpszRegistryValue);
193
 
 
194
 
            // Store the root directory for later use.
195
 
            m_strBOINCMGRDataDirectory = lpszRegistryValue;
196
 
        }
197
 
    }
198
 
 
199
 
    // Cleanup
200
 
        if (hkSetupHive) RegCloseKey(hkSetupHive);
201
 
    if (lpszRegistryValue) free(lpszRegistryValue);
202
 
 
203
 
 
204
 
    //
205
 
    // Determine BOINCMgr Root Directory
206
 
    //
207
 
    TCHAR   szPath[MAX_PATH-1];
208
 
 
209
 
    // change the current directory to the boinc install directory
210
 
    GetModuleFileName(NULL, szPath, (sizeof(szPath)/sizeof(TCHAR)));
211
 
                
212
 
    TCHAR *pszProg = strrchr(szPath, '\\');
213
 
    if (pszProg) {
214
 
        szPath[pszProg - szPath + 1] = 0;
215
 
    }
216
 
 
217
 
    // Store the root directory for later use.
218
 
    m_strBOINCMGRRootDirectory = szPath;
219
 
 
220
 
#endif
221
 
 
222
 
#ifdef __WXMAC__
223
 
 
224
 
#if wxCHECK_VERSION(2,8,0)
225
 
// In wxMac-2.8.7, default wxListCtrl::RefreshItem() does not work
226
 
// so use traditional generic implementation.
227
 
    wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), 1);
228
 
#endif
229
 
        
230
 
    wxString strDirectory = wxEmptyString;
231
 
    bool success;
232
 
    ProcessSerialNumber psn;
233
 
 
234
 
    // Set the current directory ahead of the application launch so the core
235
 
    //   client can find its files
236
 
 
237
 
    // The mac installer sets the "setuid & setgid" bits for the 
238
 
    // BOINC Manager and core client so any user can run them and 
239
 
    // they can operate on shared data.
240
 
    strDirectory = wxT("/Library/Application Support/");
241
 
 
242
 
    success = ::wxSetWorkingDirectory(strDirectory);
243
 
    if (success) {
244
 
        // If SetWD failed, don't create a directory in wrong place
245
 
        strDirectory += wxT("BOINC Data");  // We don't customize BOINC Data directory name for branding
246
 
        if (! g_use_sandbox) {
247
 
            if (! wxDirExists(strDirectory))
248
 
                success = wxMkdir(strDirectory, 0777);    // Does nothing if dir exists
249
 
        }
250
 
        success = ::wxSetWorkingDirectory(strDirectory);
251
 
//    wxChar *wd = wxGetWorkingDirectory(buf, 1000);  // For debugging
252
 
    }
253
 
 
254
 
    if (!success)  // wxSetWorkingDirectory("/Library/Application Support/BOINC Data") FAILED
255
 
        errCode = -1016;
256
 
#endif      // __WXMAC__
257
 
 
258
 
#ifdef SANDBOX
259
 
    // Make sure owners, groups and permissions are correct for the current setting of g_use_sandbox
260
 
    if (!errCode) {
261
 
#if (defined(__WXMAC__) && defined(_DEBUG))     // TODO: implement this for other platforms
262
 
        // GDB can't attach to applications which are running as a different user   
263
 
        //  or group, so fix up data with current user and group during debugging
264
 
        if (check_security(g_use_sandbox, true)) {
265
 
            CreateBOINCUsersAndGroups();
266
 
            SetBOINCDataOwnersGroupsAndPermissions();
267
 
            SetBOINCAppOwnersGroupsAndPermissions(NULL);
268
 
        }
269
 
#endif  // __WXMAC__ && _DEBUG
270
 
        errCode = check_security(g_use_sandbox, true);
271
 
    }
272
 
       
273
 
    if (errCode) {
274
 
        wxString strDialogMessage = wxEmptyString;
275
 
        strDialogMessage.Printf(
276
 
            _("BOINC ownership or permissions are not set properly; please reinstall BOINC.\n(Error code %d)"),
277
 
            errCode
278
 
        );
279
 
        wxMessageDialog* pDlg = new wxMessageDialog(NULL, strDialogMessage, wxT(""), wxOK);
280
 
        GetCurrentProcess(&psn);
281
 
        SetFrontProcess(&psn);  // Shows process if hidden
282
 
        pDlg->ShowModal();
283
 
        if (pDlg)
284
 
            pDlg->Destroy();
285
 
        return false;
286
 
    }
287
 
#endif      // SANDBOX
288
 
 
289
 
    // Initialize the BOINC Diagnostics Framework
290
 
    int dwDiagnosticsFlags =
291
 
        BOINC_DIAG_DUMPCALLSTACKENABLED | 
292
 
        BOINC_DIAG_HEAPCHECKENABLED |
293
 
        BOINC_DIAG_MEMORYLEAKCHECKENABLED |
294
 
#if defined(__WXMSW__) || defined(__WXMAC__)
295
 
        BOINC_DIAG_REDIRECTSTDERR |
296
 
        BOINC_DIAG_REDIRECTSTDOUT |
297
 
#endif
298
 
        BOINC_DIAG_TRACETOSTDOUT;
299
 
 
300
 
    diagnostics_init(
301
 
        dwDiagnosticsFlags,
302
 
        "stdoutgui",
303
 
        "stderrgui"
304
 
    );
305
 
 
306
 
    // Enable Logging and Trace Masks
307
 
    m_pLog = new wxLogBOINC();
308
 
    wxLog::SetActiveTarget(m_pLog);
309
 
 
310
 
    m_pLog->AddTraceMask(wxT("Function Start/End"));
311
 
    m_pLog->AddTraceMask(wxT("Function Status"));
312
 
 
313
 
    // Enable known image types
314
 
    wxImage::AddHandler(new wxXPMHandler);
315
 
        wxImage::AddHandler(new wxPNGHandler);
316
 
        wxImage::AddHandler(new wxGIFHandler);
317
 
        wxImage::AddHandler(new wxICOHandler);
318
 
 
319
 
    // Initialize the internationalization module
320
 
    m_pLocale = new wxLocale();
321
 
    wxASSERT(m_pLocale);
322
 
 
323
 
    // Look for the localization files by absolute and relative locations.
324
 
    //   preference given to the absolute location.
325
 
    m_pLocale->Init(iSelectedLanguage);
326
 
    if (!m_strBOINCMGRRootDirectory.IsEmpty()) {
327
 
        m_pLocale->AddCatalogLookupPathPrefix(
328
 
            wxString(m_strBOINCMGRRootDirectory + wxT("locale"))
329
 
        );
330
 
    }
331
 
    m_pLocale->AddCatalogLookupPathPrefix(wxT("locale"));
332
 
    m_pLocale->AddCatalog(wxT("BOINC Manager"));
333
 
 
334
 
    InitSupportedLanguages();
335
 
 
336
 
    // Note: JAWS for Windows will only speak the context-sensitive
337
 
    // help if you use this help provider:
338
 
    wxHelpProvider::Set(new wxHelpControllerHelpProvider());
339
 
 
340
 
    // Initialize the skin manager
341
 
    m_pSkinManager = new CSkinManager();
342
 
    wxASSERT(m_pSkinManager);
343
 
 
344
 
    m_pSkinManager->ReloadSkin(
345
 
        m_pLocale, 
346
 
        m_pConfig->Read(wxT("Skin"), 
347
 
        m_pSkinManager->GetDefaultSkinName())
348
 
    );
349
 
 
350
 
#ifdef __WXMSW__
351
 
    // Perform any last minute checks that should keep the manager
352
 
    // from starting up.
353
 
    wxString strRebootPendingFile = 
354
 
        GetRootDirectory() + wxFileName::GetPathSeparator() + wxT("RebootPending.txt");
355
 
    
356
 
    wxFileInputStream fisRebootPending(strRebootPendingFile);
357
 
    if (fisRebootPending.IsOk()) {
358
 
 
359
 
        wxMessageDialog dialog(
360
 
            NULL,
361
 
            _("A reboot is required in order for BOINC to run properly.\nPlease reboot your computer and try again."),
362
 
            _("BOINC Manager"),
363
 
            wxOK|wxICON_ERROR
364
 
        );
365
 
 
366
 
        dialog.ShowModal();
367
 
        return false;
368
 
    }
369
 
#endif
370
 
 
371
 
    // Initialize the main document
372
 
    m_pDocument = new CMainDocument();
373
 
    wxASSERT(m_pDocument);
374
 
 
375
 
    m_pDocument->OnInit();
376
 
 
377
 
    // Is there a condition in which the Simple GUI should not be used?
378
 
    if (BOINC_SIMPLEGUI == m_iGUISelected) {
379
 
 
380
 
        // Screen too small?
381
 
        if (wxGetDisplaySize().GetHeight() < 600) {
382
 
            m_iGUISelected = BOINC_ADVANCEDGUI;
383
 
        }
384
 
 
385
 
        // Screen reader in use?
386
 
#ifdef __WXMSW__
387
 
        BOOL bScreenReaderEnabled = false;
388
 
        SystemParametersInfo(SPI_GETSCREENREADER, NULL, &bScreenReaderEnabled, NULL);
389
 
        if (bScreenReaderEnabled) {
390
 
            m_iGUISelected = BOINC_ADVANCEDGUI;
391
 
        }
392
 
#endif
393
 
    }
394
 
 
395
 
#ifdef __WXMAC__
396
 
#if 0       // We may still need this code; don't remove it yet -- CAF 1/30/08
397
 
    // When running BOINC Client as a daemon / service, the menubar icon is sometimes 
398
 
    // unresponsive to mouse clicks if we create it before connecting to the Client.
399
 
    CBOINCClientManager* pcm = m_pDocument->m_pClientManager;
400
 
    if (pcm->IsSystemBooting() && pcm->IsBOINCConfiguredAsDaemon()) {
401
 
        pcm->StartupBOINCCore();
402
 
    }
403
 
#endif
404
 
#endif
405
 
 
406
 
    // Initialize the task bar icon
407
 
#if defined(__WXMSW__) || defined(__WXMAC__)
408
 
        m_pTaskBarIcon = new CTaskBarIcon(
409
 
        m_pSkinManager->GetAdvanced()->GetApplicationName(), 
410
 
        m_pSkinManager->GetAdvanced()->GetApplicationIcon(),
411
 
        m_pSkinManager->GetAdvanced()->GetApplicationDisconnectedIcon(),
412
 
        m_pSkinManager->GetAdvanced()->GetApplicationSnoozeIcon()
413
 
    );
414
 
    wxASSERT(m_pTaskBarIcon);
415
 
#endif
416
 
 
417
 
    // Detect the display info and store for later use.
418
 
    DetectDisplayInfo();
419
 
 
420
 
    // Startup the System Idle Detection code
421
 
    ClientLibraryStartup();
422
 
    IdleTrackerAttach();
423
 
 
424
 
#ifdef __WXMAC__
425
 
    s_bSkipExitConfirmation = false;
426
 
    AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP((AEEventHandlerProcPtr)QuitAppleEventHandler), 0, false );
427
 
 
428
 
    m_pMacSystemMenu = new CMacSystemMenu(
429
 
        m_pSkinManager->GetAdvanced()->GetApplicationName(), 
430
 
        m_pSkinManager->GetAdvanced()->GetApplicationIcon(),
431
 
        m_pSkinManager->GetAdvanced()->GetApplicationDisconnectedIcon(),
432
 
        m_pSkinManager->GetAdvanced()->GetApplicationSnoozeIcon()
433
 
    );
434
 
    wxASSERT(m_pMacSystemMenu);
435
 
 
436
 
    ProcessInfoRec pInfo;
437
 
    OSStatus err;
438
 
    
439
 
    GetCurrentProcess(&psn);
440
 
    memset(&pInfo, 0, sizeof(pInfo));
441
 
    pInfo.processInfoLength = sizeof( ProcessInfoRec );
442
 
    err = GetProcessInformation(&psn, &pInfo);
443
 
    if (!err) {
444
 
        psn = pInfo.processLauncher;
445
 
        memset(&pInfo, 0, sizeof(pInfo));
446
 
        pInfo.processInfoLength = sizeof( ProcessInfoRec );
447
 
        err = GetProcessInformation(&psn, &pInfo);
448
 
    }
449
 
    // Don't open main window if we were started automatically at login
450
 
    if (pInfo.processSignature == 'lgnw') {  // Login Window app
451
 
        m_bGUIVisible = false;
452
 
 
453
 
        // If the system was just started, we usually get a "Connection 
454
 
        // failed" error if we try to connect too soon, so delay a bit.
455
 
        sleep(10);
456
 
    }
457
 
#endif
458
 
 
459
 
    // Show the UI
460
 
    SetActiveGUI(m_iGUISelected, false);
461
 
    if (m_bGUIVisible) {
462
 
        SetActiveGUI(m_iGUISelected);
463
 
    } else {
464
 
#ifdef __WXMAC__
465
 
        GetCurrentProcess(&psn);
466
 
        ShowHideProcess(&psn, false);
467
 
#endif
468
 
        }
469
 
 
470
 
    return true;
471
 
}
472
 
 
473
 
 
474
 
int CBOINCGUIApp::OnExit() {
475
 
    // Shutdown the System Idle Detection code
476
 
    IdleTrackerDetach();
477
 
    ClientLibraryShutdown();
478
 
 
479
 
    if (m_pDocument) {
480
 
        m_pDocument->OnExit();
481
 
        delete m_pDocument;
482
 
    }
483
 
 
484
 
    if (m_pSkinManager) {
485
 
        m_pConfig->Write(wxT("Skin"), m_pSkinManager->GetSelectedSkin());
486
 
        delete m_pSkinManager;
487
 
    }
488
 
 
489
 
    if (m_pLocale) {
490
 
        delete m_pLocale;
491
 
    }
492
 
 
493
 
    // Save Application State
494
 
    m_pConfig->Write(wxT("AutomaticallyShutdownClient"), m_iShutdownCoreClient);
495
 
    m_pConfig->Write(wxT("DisplayShutdownClientDialog"), m_iDisplayExitDialog);
496
 
    m_pConfig->Write(wxT("DisableAutoStart"), m_iBOINCMGRDisableAutoStart);
497
 
 
498
 
    diagnostics_finish();
499
 
 
500
 
    return wxApp::OnExit();
501
 
}
502
 
 
503
 
 
504
 
void CBOINCGUIApp::OnInitCmdLine(wxCmdLineParser &parser) {
505
 
    wxApp::OnInitCmdLine(parser);
506
 
    static const wxCmdLineEntryDesc cmdLineDesc[] = {
507
 
        { wxCMD_LINE_SWITCH, wxT("a"), wxT("autostart"), _("BOINC Manager was started by the operating system automatically")},
508
 
        { wxCMD_LINE_SWITCH, wxT("s"), wxT("systray"), _("Startup BOINC so only the system tray icon is visible")},
509
 
        { wxCMD_LINE_SWITCH, wxT("b"), wxT("boincargs"), _("Startup BOINC with these optional arguments")},
510
 
        { wxCMD_LINE_SWITCH, wxT("i"), wxT("insecure"), _("disable BOINC security users and permissions")},
511
 
        { wxCMD_LINE_NONE}  //DON'T forget this line!!
512
 
    };
513
 
    parser.SetDesc(cmdLineDesc);
514
 
}
515
 
 
516
 
 
517
 
bool CBOINCGUIApp::OnCmdLineParsed(wxCmdLineParser &parser) {
518
 
    // Give default processing (-?, --help and --verbose) the chance to do something.
519
 
    wxApp::OnCmdLineParsed(parser);
520
 
    parser.Found(wxT("boincargs"), &m_strBOINCArguments);
521
 
    if (parser.Found(wxT("autostart"))) {
522
 
        m_bBOINCMGRAutoStarted = true;
523
 
    }
524
 
    if (parser.Found(wxT("systray"))) {
525
 
        m_bGUIVisible = false;
526
 
    }
527
 
    if (parser.Found(wxT("insecure"))) {
528
 
        g_use_sandbox = false;
529
 
    }
530
 
    return true;
531
 
}
532
 
 
533
 
 
534
 
void CBOINCGUIApp::DetectDisplayInfo() {
535
 
#ifdef __WXMSW__
536
 
    wxChar szWindowStation[256];
537
 
    memset(szWindowStation, 0, sizeof(szWindowStation)/sizeof(wxChar));
538
 
    wxChar szDesktop[256];
539
 
    memset(szDesktop, 0, sizeof(szDesktop)/sizeof(wxChar));
540
 
 
541
 
    if (wxWIN95 != wxGetOsVersion(NULL, NULL)) {
542
 
        // Retrieve the current window station and desktop names
543
 
        GetUserObjectInformation(
544
 
            GetProcessWindowStation(), 
545
 
            UOI_NAME, 
546
 
            szWindowStation,
547
 
            (sizeof(szWindowStation) / sizeof(wxChar)),
548
 
            NULL
549
 
        );
550
 
        GetUserObjectInformation(
551
 
            GetThreadDesktop(GetCurrentThreadId()), 
552
 
            UOI_NAME, 
553
 
            szDesktop,
554
 
            (sizeof(szDesktop) / sizeof(wxChar)),
555
 
            NULL
556
 
        );
557
 
        m_strDefaultWindowStation = szWindowStation;
558
 
        m_strDefaultDesktop = szDesktop;
559
 
    }
560
 
 
561
 
#else
562
 
    wxString p = wxString(getenv("DISPLAY"), wxConvUTF8);
563
 
    if (p) m_strDefaultDisplay = p;
564
 
#endif
565
 
 
566
 
}
567
 
 
568
 
 
569
 
void CBOINCGUIApp::InitSupportedLanguages() {
570
 
    wxInt32               iIndex = 0;
571
 
    const wxLanguageInfo* liLanguage = NULL;
572
 
 
573
 
    // Prepare the array
574
 
    m_astrLanguages.Insert(wxEmptyString, 0, wxLANGUAGE_USER_DEFINED+1);
575
 
 
576
 
    // These are just special tags so deal with them in a special way
577
 
    m_astrLanguages[wxLANGUAGE_DEFAULT]                    = _("(Automatic Detection)");
578
 
    m_astrLanguages[wxLANGUAGE_UNKNOWN]                    = _("(Unknown)");
579
 
    m_astrLanguages[wxLANGUAGE_USER_DEFINED]               = _("(User Defined)");
580
 
 
581
 
    for (iIndex = 0; iIndex <= wxLANGUAGE_USER_DEFINED; iIndex++) {
582
 
        liLanguage = wxLocale::GetLanguageInfo(iIndex);
583
 
        if (liLanguage) {
584
 
            m_astrLanguages[iIndex] = liLanguage->Description;
585
 
        }
586
 
    }
587
 
}
588
 
 
589
 
 
590
 
#ifdef __WXMAC__
591
 
 
592
 
// Set s_bSkipExitConfirmation to true if cancelled because of logging out or shutting down
593
 
OSErr CBOINCGUIApp::QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon ) {
594
 
        DescType                senderType;
595
 
        Size                    actualSize;
596
 
        ProcessSerialNumber     SenderPSN, ourPSN;
597
 
        Boolean                 isSame;
598
 
        ProcessInfoRec          pInfo;
599
 
        FSSpec                  fileSpec;
600
 
        OSStatus                anErr;
601
 
 
602
 
        // Refuse to quit if a modal dialog is open.  Search for the dialog 
603
 
        // by ID since all of BOINC Manager's dialog IDs are 10000.
604
 
        // Unfortunately, I know of no way to disable the Quit item in our Dock menu
605
 
        if (wxDynamicCast(wxWindow::FindWindowById(ID_ANYDIALOG), wxDialog)) {
606
 
            SysBeep(4);
607
 
            return userCanceledErr;
608
 
        }
609
 
                
610
 
       anErr = AEGetAttributePtr(appleEvt, keyAddressAttr, typeProcessSerialNumber,
611
 
                                    &senderType, &SenderPSN, sizeof(SenderPSN), &actualSize);
612
 
 
613
 
        if (anErr == noErr) {
614
 
             
615
 
            GetCurrentProcess(&ourPSN);
616
 
 
617
 
            anErr = SameProcess(&SenderPSN, &ourPSN, &isSame);
618
 
 
619
 
            if (anErr == noErr) {
620
 
                if (!isSame) {
621
 
 
622
 
                pInfo.processInfoLength = sizeof( ProcessInfoRec );
623
 
                pInfo.processName = NULL;
624
 
                pInfo.processAppSpec = &fileSpec;
625
 
 
626
 
                anErr = GetProcessInformation(&SenderPSN, &pInfo);
627
 
 
628
 
                // Consider a Quit command from our Dock menu as coming from this application
629
 
                if (pInfo.processSignature != 'dock') {
630
 
                    s_bSkipExitConfirmation = true; // Not from our app, our dock icon or our taskbar icon
631
 
                    wxGetApp().ExitMainLoop();  // Prevents wxMac from issuing events to closed frames
632
 
                }
633
 
            }
634
 
        }
635
 
    }
636
 
    
637
 
    return wxGetApp().MacHandleAEQuit((AppleEvent*)appleEvt, reply);
638
 
}
639
 
 
640
 
#endif
641
 
 
642
 
 
643
 
int CBOINCGUIApp::ClientLibraryStartup() {
644
 
#ifdef __WXMSW__
645
 
    ::ClientLibraryStartup();
646
 
#endif
647
 
    return 0;
648
 
}
649
 
 
650
 
 
651
 
int CBOINCGUIApp::IdleTrackerAttach() {
652
 
#ifdef __WXMSW__
653
 
    ::IdleTrackerAttach();
654
 
#endif
655
 
    return 0;
656
 
}
657
 
 
658
 
 
659
 
int CBOINCGUIApp::IdleTrackerDetach() {
660
 
#ifdef __WXMSW__
661
 
    ::IdleTrackerDetach();
662
 
#endif
663
 
    return 0;
664
 
}
665
 
 
666
 
 
667
 
int CBOINCGUIApp::ClientLibraryShutdown() {
668
 
#ifdef __WXMSW__
669
 
    ::ClientLibraryShutdown();
670
 
#endif
671
 
    return 0;
672
 
}
673
 
 
674
 
 
675
 
int CBOINCGUIApp::UpdateSystemIdleDetection() {
676
 
#ifdef __WXMSW__
677
 
    return BOINCGetIdleTickCount();
678
 
#else
679
 
    return TRUE;
680
 
#endif
681
 
}
682
 
 
683
 
 
684
 
int CBOINCGUIApp::StartBOINCScreensaverTest() {
685
 
#ifdef __WXMSW__
686
 
    wxString strExecute = wxEmptyString;
687
 
    wxChar   szExecutableDirectory[4096];
688
 
    memset(szExecutableDirectory, 0, sizeof(szExecutableDirectory));
689
 
 
690
 
    // On Windows the screensaver is located in the Windows directory.
691
 
    GetWindowsDirectory(
692
 
        szExecutableDirectory,
693
 
        (sizeof(szExecutableDirectory) / sizeof(wxChar))
694
 
    );
695
 
 
696
 
    // Append boinc.scr to the end of the strExecute string and get ready to rock
697
 
    strExecute = wxT("\"") + wxString(szExecutableDirectory) + wxT("\\boinc.scr\" /t");
698
 
    ::wxExecute(strExecute);
699
 
#endif
700
 
    return 0;
701
 
}
702
 
 
703
 
 
704
 
// The skin has changed and all UI elements need to reload their bitmaps.
705
 
//
706
 
void CBOINCGUIApp::FireReloadSkin() {
707
 
    if (m_pFrame) {
708
 
            m_pFrame->FireReloadSkin();
709
 
    }
710
 
    if (m_pTaskBarIcon) {
711
 
            m_pTaskBarIcon->FireReloadSkin();
712
 
    }
713
 
}
714
 
 
715
 
 
716
 
bool CBOINCGUIApp::SetActiveGUI(int iGUISelection, bool bShowWindow) {
717
 
    CBOINCBaseFrame* pNewFrame = NULL;
718
 
    CBOINCBaseFrame* pOldFrame = m_pFrame;
719
 
 
720
 
    // Create the new window
721
 
    if ((iGUISelection != m_iGUISelected) || !m_pFrame) {
722
 
        switch(iGUISelection) {
723
 
            case BOINC_SIMPLEGUI:
724
 
            default:
725
 
                // Initialize the simple gui window
726
 
                pNewFrame = new CSimpleFrame(
727
 
                    m_pSkinManager->GetAdvanced()->GetApplicationName(), 
728
 
                    m_pSkinManager->GetAdvanced()->GetApplicationIcon(),
729
 
                    m_pSkinManager->GetAdvanced()->GetApplicationIcon32()
730
 
                );
731
 
                break;
732
 
            case BOINC_ADVANCEDGUI:
733
 
                // Initialize the advanced gui window
734
 
                pNewFrame = new CAdvancedFrame(
735
 
                    m_pSkinManager->GetAdvanced()->GetApplicationName(), 
736
 
                    m_pSkinManager->GetAdvanced()->GetApplicationIcon(),
737
 
                    m_pSkinManager->GetAdvanced()->GetApplicationIcon32()
738
 
                );
739
 
                break;
740
 
        }
741
 
        wxASSERT(pNewFrame);
742
 
 
743
 
        if (pNewFrame) {
744
 
            SetTopWindow(pNewFrame);
745
 
 
746
 
            // Store the new frame for future use
747
 
            m_pFrame = pNewFrame;
748
 
 
749
 
            // Hide the old one if it exists.  We must do this 
750
 
            // after updating m_pFrame to prevent Mac OSX from
751
 
            // hiding the application
752
 
            if (pOldFrame) pOldFrame->Hide();
753
 
 
754
 
            // Show the new frame if needed
755
 
            if (pNewFrame && bShowWindow) pNewFrame->Show();
756
 
 
757
 
            // Delete the old one if it exists
758
 
            if (pOldFrame) pOldFrame->Destroy();
759
 
        }
760
 
    }
761
 
 
762
 
    // Show the new frame if needed 
763
 
    if (m_pFrame && bShowWindow) m_pFrame->Show();
764
 
 
765
 
    m_iGUISelected = iGUISelection;
766
 
    m_pConfig->Write(wxT("GUISelection"), iGUISelection);
767
 
 
768
 
    return true;
769
 
}
770
 
 
771
 
 
772
 
int CBOINCGUIApp::ConfirmExit() {
773
 
    CSkinAdvanced*  pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
774
 
    CMainDocument*  pDoc = wxGetApp().GetDocument();
775
 
    wxString        strConnectedCompter = wxEmptyString;
776
 
    int             retval = 0;
777
 
 
778
 
    wxASSERT(pDoc);
779
 
    wxASSERT(pSkinAdvanced);
780
 
    wxASSERT(wxDynamicCast(pDoc, CMainDocument));
781
 
    wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
782
 
    
783
 
    // If we are connected to the local core client and the manager is exiting
784
 
    //   give the user the option to shutdown the core client, even if the
785
 
    //   manager didn't launch the core client anyway.
786
 
    if (!pDoc->m_pClientManager->WasBOINCStartedByManager()) {
787
 
        pDoc->GetConnectedComputerName(strConnectedCompter);
788
 
        if (!pDoc->IsComputerNameLocal(strConnectedCompter)) {
789
 
            // Don't shutdown remote clients
790
 
            return 1;
791
 
        }
792
 
    }
793
 
 
794
 
#ifdef __WXMAC__
795
 
    // Don't run confirmation dialog if logging out or shutting down
796
 
    if (s_bSkipExitConfirmation)
797
 
        return 1;
798
 
 
799
 
    if (!m_iDisplayExitDialog) {
800
 
        return 1;   // User doesn't want to display the dialog and wants to shutdown the client.
801
 
    }
802
 
#else
803
 
    if (!m_iDisplayExitDialog) {
804
 
                return 1;   // User doesn't want to display the dialog and just wants to use their previous value
805
 
        }
806
 
#endif
807
 
 
808
 
#ifdef __WXMAC__
809
 
    // Don't run confirmation dialog if logging out or shutting down
810
 
    if (s_bSkipExitConfirmation)
811
 
        return 1;
812
 
 
813
 
    ProcessSerialNumber psn;
814
 
 
815
 
    GetCurrentProcess(&psn);
816
 
    bool wasVisible = IsProcessVisible(&psn);
817
 
    SetFrontProcess(&psn);  // Shows process if hidden
818
 
#endif
819
 
 
820
 
    CDlgExitMessage dlg(NULL);
821
 
 
822
 
    if (!pSkinAdvanced->GetExitMessage().IsEmpty()) {
823
 
        dlg.m_DialogExitMessage->SetLabel(pSkinAdvanced->GetExitMessage());
824
 
    }
825
 
 
826
 
#ifdef __WXMSW__
827
 
    if (m_iShutdownCoreClient) {
828
 
        dlg.m_DialogShutdownCoreClient->SetValue(TRUE);
829
 
    }
830
 
#endif
831
 
 
832
 
    if (m_iDisplayExitDialog) {
833
 
        dlg.m_DialogDisplay->SetValue(FALSE);
834
 
    }
835
 
 
836
 
    dlg.Fit();
837
 
    dlg.Centre();
838
 
 
839
 
    if (wxID_OK == dlg.ShowModal()) {
840
 
#ifndef __WXMSW__
841
 
        s_bSkipExitConfirmation = true;     // Don't ask twice (only affects Mac)
842
 
#else
843
 
        m_iShutdownCoreClient = dlg.m_DialogShutdownCoreClient->GetValue();
844
 
#endif
845
 
        m_iDisplayExitDialog = !dlg.m_DialogDisplay->GetValue();
846
 
        retval = true;
847
 
 
848
 
    }
849
 
 
850
 
#ifdef __WXMAC__
851
 
    if (!wasVisible) {
852
 
        ShowHideProcess(&psn, false);
853
 
    }
854
 
#endif
855
 
 
856
 
    return retval;
857
 
}
858
 
 
859
 
 
860
 
const char *BOINC_RCSID_487cbf3018 = "$Id: BOINCGUIApp.cpp 16487 2008-11-13 10:57:16Z charlief $";
 
1
// This file is part of BOINC.
 
2
// http://boinc.berkeley.edu
 
3
// Copyright (C) 2008 University of California
 
4
//
 
5
// BOINC is free software; you can redistribute it and/or modify it
 
6
// under the terms of the GNU Lesser General Public License
 
7
// as published by the Free Software Foundation,
 
8
// either version 3 of the License, or (at your option) any later version.
 
9
//
 
10
// BOINC is distributed in the hope that it will be useful,
 
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
13
// See the GNU Lesser General Public License for more details.
 
14
//
 
15
// You should have received a copy of the GNU Lesser General Public License
 
16
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
 
17
 
 
18
#if defined(__GNUG__) && !defined(__APPLE__)
 
19
#pragma implementation "BOINCGUIApp.h"
 
20
#endif
 
21
 
 
22
#ifdef __WXMAC__
 
23
#include <Carbon/Carbon.h>
 
24
#include "filesys.h"
 
25
#include "util.h"
 
26
#if (defined(SANDBOX) && defined(_DEBUG))
 
27
#include "SetupSecurity.h"
 
28
#endif
 
29
#include "sandbox.h"
 
30
#endif
 
31
 
 
32
#include "stdwx.h"
 
33
#include "diagnostics.h"
 
34
#include "network.h"
 
35
#include "util.h"
 
36
#include "mfile.h"
 
37
#include "miofile.h"
 
38
#include "parse.h"
 
39
#include "idlemon.h"
 
40
#include "Events.h"
 
41
#include "common/wxFlatNotebook.h"
 
42
#include "BOINCInternetFSHandler.h"
 
43
//#include "BOINCMemoryFSHandler.h"
 
44
#include "LogBOINC.h"
 
45
#include "BOINCGUIApp.h"
 
46
#include "SkinManager.h"
 
47
#include "MainDocument.h"
 
48
#include "BOINCClientManager.h"
 
49
#include "BOINCTaskBar.h"
 
50
#include "BOINCBaseFrame.h"
 
51
#include "AdvancedFrame.h"
 
52
#include "sg_ImageLoader.h"
 
53
#include "sg_StatImageLoader.h"
 
54
#include "sg_BoincSimpleGUI.h"
 
55
#include "DlgExitMessage.h"
 
56
#include "DlgEventLog.h"
 
57
#include "procinfo.h"
 
58
 
 
59
 
 
60
DEFINE_EVENT_TYPE(wxEVT_RPC_FINISHED)
 
61
 
 
62
IMPLEMENT_APP(CBOINCGUIApp)
 
63
IMPLEMENT_DYNAMIC_CLASS(CBOINCGUIApp, wxApp)
 
64
 
 
65
BEGIN_EVENT_TABLE (CBOINCGUIApp, wxApp)
 
66
    EVT_RPC_FINISHED(CBOINCGUIApp::OnRPCFinished)
 
67
END_EVENT_TABLE ()
 
68
 
 
69
 
 
70
bool s_bSkipExitConfirmation = false;
 
71
 
 
72
#ifdef __WXMAC__
 
73
 
 
74
// Set s_bSkipExitConfirmation to true if cancelled because of logging out or shutting down
 
75
OSErr QuitAppleEventHandler( const AppleEvent *appleEvt, AppleEvent* reply, UInt32 refcon ) {
 
76
        DescType            senderType;
 
77
        Size                actualSize;
 
78
        ProcessSerialNumber SenderPSN;
 
79
        ProcessInfoRec      pInfo;
 
80
        FSSpec              fileSpec;
 
81
        OSStatus            anErr;
 
82
 
 
83
        // Refuse to quit if a modal dialog is open.  
 
84
        // Unfortunately, I know of no way to disable the Quit item in our Dock menu
 
85
        if (wxGetApp().IsModalDialogDisplayed()) {
 
86
            SysBeep(4);
 
87
            return userCanceledErr;
 
88
        }
 
89
                
 
90
        anErr = AEGetAttributePtr(appleEvt, keyAddressAttr, typeProcessSerialNumber,
 
91
                                    &senderType, &SenderPSN, sizeof(SenderPSN), &actualSize);
 
92
 
 
93
        if (anErr == noErr) {
 
94
            pInfo.processInfoLength = sizeof( ProcessInfoRec );
 
95
            pInfo.processName = NULL;
 
96
            pInfo.processAppSpec = &fileSpec;
 
97
 
 
98
            anErr = GetProcessInformation(&SenderPSN, &pInfo);
 
99
 
 
100
            // Consider a Quit command from our Dock menu as coming from this application
 
101
            if ( (pInfo.processSignature != 'dock') && (pInfo.processSignature != 'BNC!') ) {
 
102
                s_bSkipExitConfirmation = true; // Not from our app, our dock icon or our taskbar icon
 
103
                wxGetApp().ExitMainLoop();  // Prevents wxMac from issuing events to closed frames
 
104
            }
 
105
        }
 
106
    
 
107
    return wxGetApp().MacHandleAEQuit((AppleEvent*)appleEvt, reply);
 
108
}
 
109
 
 
110
#endif
 
111
 
 
112
 
 
113
bool CBOINCGUIApp::OnInit() {
 
114
    // Initialize globals
 
115
#ifdef SANDBOX
 
116
    g_use_sandbox = true;
 
117
#else
 
118
    g_use_sandbox = false;
 
119
#endif
 
120
 
 
121
    s_bSkipExitConfirmation = false;
 
122
 
 
123
    // Initialize class variables
 
124
    m_pLocale = NULL;
 
125
    m_pSkinManager = NULL;
 
126
    m_pFrame = NULL;
 
127
    m_pDocument = NULL;
 
128
    m_pTaskBarIcon = NULL;
 
129
    m_pEventLog = NULL;
 
130
#ifdef __WXMAC__
 
131
    m_pMacSystemMenu = NULL;
 
132
#endif
 
133
    m_strBOINCMGRExecutableName = wxEmptyString;
 
134
    m_strBOINCMGRRootDirectory = wxEmptyString;
 
135
    m_strBOINCMGRDataDirectory = wxEmptyString;
 
136
    m_strHostNameArg = wxEmptyString;
 
137
    m_strPasswordArg = wxEmptyString;
 
138
    m_iRPCPortArg = GUI_RPC_PORT;
 
139
    m_strBOINCArguments = wxEmptyString;
 
140
    m_bAccessibilityEnabled = false;
 
141
    m_bGUIVisible = true;
 
142
    m_bDebugSkins = false;
 
143
    m_bMultipleInstancesOK = false;
 
144
    m_strDefaultWindowStation = wxEmptyString;
 
145
    m_strDefaultDesktop = wxEmptyString;
 
146
    m_strDefaultDisplay = wxEmptyString;
 
147
    m_bBOINCMGRAutoStarted = false;
 
148
    m_iBOINCMGRDisableAutoStart = 0;
 
149
    m_iShutdownCoreClient = 0;
 
150
    m_iDisplayExitDialog = 1;
 
151
    m_iGUISelected = BOINC_SIMPLEGUI;
 
152
    m_bSafeMessageBoxDisplayed = 0;
 
153
#ifdef __WXMSW__
 
154
    m_hClientLibraryDll = NULL;
 
155
#endif
 
156
 
 
157
 
 
158
    // Initialize local variables
 
159
    int      iErrorCode = 0;
 
160
    int      iSelectedLanguage = 0;
 
161
    bool     bOpenEventLog = false;
 
162
    wxString strDesiredSkinName = wxEmptyString;
 
163
    wxString strDialogMessage = wxEmptyString;
 
164
    bool     success = false;
 
165
 
 
166
 
 
167
    // Configure wxWidgets platform specific code
 
168
#ifdef __WXMSW__
 
169
    wxSystemOptions::SetOption(wxT("msw.staticbox.optimized-paint"), 0);
 
170
#endif
 
171
#ifdef __WXMAC__
 
172
    // In wxMac-2.8.7, default wxListCtrl::RefreshItem() does not work
 
173
    // so use traditional generic implementation.
 
174
    // This has been fixed in wxMac-2.8.8, but the Mac native implementation:
 
175
    //  - takes 3 times the CPU time as the Mac generic version.
 
176
    //  - seems to always redraw entire control even if asked to refresh only one row.
 
177
    //  - causes major flicker of progress bars, (probably due to full redraws.)
 
178
    wxSystemOptions::SetOption(wxT("mac.listctrl.always_use_generic"), 1);
 
179
 
 
180
    AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP((AEEventHandlerProcPtr)QuitAppleEventHandler), 0, false );
 
181
 
 
182
    // Cache the current process serial number
 
183
    GetCurrentProcess(&m_psnCurrentProcess);
 
184
#endif
 
185
 
 
186
 
 
187
    // Commandline parsing is done in wxApp::OnInit()
 
188
    if (!wxApp::OnInit()) {
 
189
        return false;
 
190
    }
 
191
 
 
192
    if (g_use_sandbox) {
 
193
        wxCHANGE_UMASK(2);  // Set file creation mask to be writable by both user and group
 
194
                            // Our umask will be inherited by all our child processes
 
195
    }
 
196
 
 
197
    // Setup application and company information
 
198
    SetAppName(wxT("BOINC Manager"));
 
199
    SetVendorName(wxT("Space Sciences Laboratory, U.C. Berkeley"));
 
200
 
 
201
 
 
202
    // Initialize the configuration storage module
 
203
    m_pConfig = new wxConfig(GetAppName());
 
204
    wxConfigBase::Set(m_pConfig);
 
205
    wxASSERT(m_pConfig);
 
206
 
 
207
 
 
208
    // Restore Application State
 
209
    m_pConfig->SetPath(wxT("/"));
 
210
    m_pConfig->Read(wxT("AutomaticallyShutdownClient"), &m_iShutdownCoreClient, 0L);
 
211
    m_pConfig->Read(wxT("DisplayShutdownClientDialog"), &m_iDisplayExitDialog, 1L);
 
212
    m_pConfig->Read(wxT("DisableAutoStart"), &m_iBOINCMGRDisableAutoStart, 0L);
 
213
    m_pConfig->Read(wxT("Language"), &iSelectedLanguage, 0L);
 
214
    m_pConfig->Read(wxT("GUISelection"), &m_iGUISelected, BOINC_SIMPLEGUI);
 
215
    m_pConfig->Read(wxT("EventLogOpen"), &bOpenEventLog);
 
216
 
 
217
 
 
218
    // Should we abort the BOINC Manager startup process?
 
219
    if (m_bBOINCMGRAutoStarted && m_iBOINCMGRDisableAutoStart) {
 
220
        return false;
 
221
    }
 
222
 
 
223
    // Detect if a program that is defined as an accessibility aid is running
 
224
    DetectAccessibilityEnabled();
 
225
 
 
226
    // Detect where BOINC Manager executable name.
 
227
    DetectExecutableName();
 
228
 
 
229
    // Detect where BOINC Manager was installed too.
 
230
    DetectRootDirectory();
 
231
 
 
232
    // Detect where the BOINC Data files are.
 
233
    DetectDataDirectory();
 
234
 
 
235
 
 
236
    // Switch the current directory to the BOINC Data directory
 
237
    if (!GetDataDirectory().IsEmpty()) {
 
238
        success = wxSetWorkingDirectory(GetDataDirectory());
 
239
        if (!success) {
 
240
            if (!g_use_sandbox) {
 
241
                if (!wxDirExists(GetDataDirectory())) {
 
242
                    success = wxMkdir(GetDataDirectory(), 0777);    // Does nothing if dir exists
 
243
                }
 
244
            }
 
245
        }
 
246
    }
 
247
 
 
248
    if (!success) iErrorCode = -1016;
 
249
 
 
250
    // Initialize the BOINC Diagnostics Framework
 
251
    int dwDiagnosticsFlags =
 
252
        BOINC_DIAG_DUMPCALLSTACKENABLED | 
 
253
        BOINC_DIAG_HEAPCHECKENABLED |
 
254
        BOINC_DIAG_MEMORYLEAKCHECKENABLED |
 
255
#if defined(__WXMSW__) || defined(__WXMAC__)
 
256
        BOINC_DIAG_REDIRECTSTDERR |
 
257
        BOINC_DIAG_REDIRECTSTDOUT |
 
258
#endif
 
259
        BOINC_DIAG_TRACETOSTDOUT;
 
260
 
 
261
    diagnostics_init(
 
262
        dwDiagnosticsFlags,
 
263
        "stdoutgui",
 
264
        "stderrgui"
 
265
    );
 
266
 
 
267
 
 
268
    // Enable Logging and Trace Masks
 
269
    m_pLog = new wxLogBOINC();
 
270
    wxLog::SetActiveTarget(m_pLog);
 
271
 
 
272
    m_pLog->AddTraceMask(wxT("Function Start/End"));
 
273
    m_pLog->AddTraceMask(wxT("Function Status"));
 
274
 
 
275
 
 
276
    // Initialize the internationalization module
 
277
#ifdef __WXMSW__
 
278
    // On Windows, set all locales for this thread on a per-thread basis
 
279
    _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
 
280
#endif
 
281
    m_pLocale = new wxLocale();
 
282
    wxASSERT(m_pLocale);
 
283
 
 
284
 
 
285
    // Look for the localization files by absolute and relative locations.
 
286
    //   preference given to the absolute location.
 
287
    m_pLocale->Init(iSelectedLanguage);
 
288
    if (!m_strBOINCMGRRootDirectory.IsEmpty()) {
 
289
        m_pLocale->AddCatalogLookupPathPrefix(
 
290
            wxString(m_strBOINCMGRRootDirectory + wxT("locale"))
 
291
        );
 
292
    }
 
293
    m_pLocale->AddCatalogLookupPathPrefix(wxT("locale"));
 
294
    m_pLocale->AddCatalog(wxT("BOINC-Manager"));
 
295
    m_pLocale->AddCatalog(wxT("BOINC-Client"));
 
296
 
 
297
    InitSupportedLanguages();
 
298
 
 
299
 
 
300
    // Note: JAWS for Windows will only speak the context-sensitive
 
301
    // help if you use this help provider:
 
302
    wxHelpProvider::Set(new wxHelpControllerHelpProvider());
 
303
 
 
304
 
 
305
#ifdef SANDBOX
 
306
    // Make sure owners, groups and permissions are correct for the current setting of g_use_sandbox
 
307
    if (!iErrorCode) {
 
308
#if (defined(__WXMAC__) && defined(_DEBUG))     // TODO: implement this for other platforms
 
309
        // GDB can't attach to applications which are running as a different user   
 
310
        //  or group, so fix up data with current user and group during debugging
 
311
        if (check_security(g_use_sandbox, true)) {
 
312
            CreateBOINCUsersAndGroups();
 
313
            SetBOINCDataOwnersGroupsAndPermissions();
 
314
            SetBOINCAppOwnersGroupsAndPermissions(NULL);
 
315
        }
 
316
#endif
 
317
        iErrorCode = check_security(g_use_sandbox, true);
 
318
    }
 
319
 
 
320
    if (iErrorCode) {
 
321
 
 
322
        ShowApplication(true);
 
323
 
 
324
        if (iErrorCode == -1099) {
 
325
            strDialogMessage = 
 
326
                _("You currently are not authorized to manage the client.\n\nTo run BOINC as this user, please:\n  - reinstall BOINC answering \"Yes\" to the question about\n     non-administrative users\n or\n  - contact your administrator to add you to the 'boinc_master'\n     user group.");
 
327
        } else {
 
328
        strDialogMessage.Printf(
 
329
                _("BOINC ownership or permissions are not set properly; please reinstall BOINC.\n(Error code %d)"),
 
330
            iErrorCode
 
331
        );
 
332
 
 
333
        }
 
334
        wxMessageDialog* pDlg = new wxMessageDialog(NULL, strDialogMessage, wxT("BOINC Manager"), wxOK);
 
335
 
 
336
        pDlg->ShowModal();
 
337
        if (pDlg)
 
338
            pDlg->Destroy();
 
339
 
 
340
        return false;
 
341
    }
 
342
#endif      // SANDBOX
 
343
 
 
344
 
 
345
    // Enable known image types
 
346
    wxInitAllImageHandlers();
 
347
 
 
348
    // Enable additional file system type handlers
 
349
    wxFileSystem::AddHandler(new wxMemoryFSHandler);
 
350
    wxFileSystem::AddHandler(new CBOINCInternetFSHandler);
 
351
 
 
352
    // Initialize the skin manager
 
353
    m_pSkinManager = new CSkinManager(m_bDebugSkins);
 
354
    wxASSERT(m_pSkinManager);
 
355
 
 
356
 
 
357
    // Load desired manager skin
 
358
    m_pConfig->Read(wxT("Skin"), &strDesiredSkinName, m_pSkinManager->GetDefaultSkinName());
 
359
    m_pSkinManager->ReloadSkin(
 
360
        m_pLocale, 
 
361
        strDesiredSkinName
 
362
    );
 
363
 
 
364
 
 
365
#ifdef __WXMSW__
 
366
    // Perform any last minute checks that should keep the manager
 
367
    // from starting up.
 
368
    wxString strRebootPendingFile = 
 
369
        GetRootDirectory() + wxFileName::GetPathSeparator() + wxT("RebootPending.txt");
 
370
    
 
371
    if (wxFile::Exists(strRebootPendingFile)) {
 
372
        wxMessageDialog dialog(
 
373
            NULL,
 
374
            _("A reboot is required in order for BOINC to run properly.\nPlease reboot your computer and try again."),
 
375
            _("BOINC Manager"),
 
376
            wxOK|wxICON_ERROR
 
377
        );
 
378
 
 
379
        dialog.ShowModal();
 
380
        return false;
 
381
    }
 
382
#endif
 
383
 
 
384
    // Detect if BOINC Manager is already running, if so, bring it into the
 
385
    // foreground and then exit.
 
386
    if (!m_bMultipleInstancesOK) {
 
387
        if (DetectDuplicateInstance()) {
 
388
            return false;
 
389
        }
 
390
    }
 
391
 
 
392
    // Initialize the main document
 
393
    m_pDocument = new CMainDocument();
 
394
    wxASSERT(m_pDocument);
 
395
 
 
396
    m_pDocument->OnInit();
 
397
 
 
398
 
 
399
    // Is there a condition in which the Simple GUI should not be used?
 
400
    if (BOINC_SIMPLEGUI == m_iGUISelected) {
 
401
 
 
402
        // Screen too small?
 
403
        if (wxGetDisplaySize().GetHeight() < 600) {
 
404
            m_iGUISelected = BOINC_ADVANCEDGUI;
 
405
        }
 
406
 
 
407
        // Screen reader in use?
 
408
        if (IsAccessibilityEnabled()) {
 
409
            m_iGUISelected = BOINC_ADVANCEDGUI;
 
410
        }
 
411
    }
 
412
 
 
413
 
 
414
    // Initialize the task bar icon
 
415
        m_pTaskBarIcon = new CTaskBarIcon(
 
416
        m_pSkinManager->GetAdvanced()->GetApplicationName(), 
 
417
        m_pSkinManager->GetAdvanced()->GetApplicationIcon(),
 
418
        m_pSkinManager->GetAdvanced()->GetApplicationDisconnectedIcon(),
 
419
        m_pSkinManager->GetAdvanced()->GetApplicationSnoozeIcon()
 
420
    );
 
421
    wxASSERT(m_pTaskBarIcon);
 
422
#ifdef __WXMAC__
 
423
    m_pMacSystemMenu = new CMacSystemMenu(
 
424
        m_pSkinManager->GetAdvanced()->GetApplicationName(), 
 
425
        m_pSkinManager->GetAdvanced()->GetApplicationIcon(),
 
426
        m_pSkinManager->GetAdvanced()->GetApplicationDisconnectedIcon(),
 
427
        m_pSkinManager->GetAdvanced()->GetApplicationSnoozeIcon()
 
428
    );
 
429
    wxASSERT(m_pMacSystemMenu);
 
430
#endif
 
431
 
 
432
 
 
433
    // Detect the display info and store for later use.
 
434
    DetectDisplayInfo();
 
435
 
 
436
 
 
437
    // Startup the System Idle Detection code
 
438
    IdleTrackerAttach();
 
439
 
 
440
#ifdef __WXMAC__
 
441
    ProcessSerialNumber psn;
 
442
    ProcessInfoRec pInfo;
 
443
    OSStatus err;
 
444
    
 
445
    memset(&pInfo, 0, sizeof(pInfo));
 
446
    pInfo.processInfoLength = sizeof( ProcessInfoRec );
 
447
    err = GetProcessInformation(&m_psnCurrentProcess, &pInfo);
 
448
    if (!err) {
 
449
        psn = pInfo.processLauncher;
 
450
        memset(&pInfo, 0, sizeof(pInfo));
 
451
        pInfo.processInfoLength = sizeof( ProcessInfoRec );
 
452
        err = GetProcessInformation(&psn, &pInfo);
 
453
    }
 
454
    // Don't open main window if we were started automatically at login
 
455
    if (pInfo.processSignature == 'lgnw') {  // Login Window app
 
456
        m_bGUIVisible = false;
 
457
 
 
458
        // If the system was just started, we usually get a "Connection 
 
459
        // failed" error if we try to connect too soon, so delay a bit.
 
460
        sleep(10);
 
461
    }
 
462
#endif
 
463
 
 
464
 
 
465
    // Show the UI
 
466
    SetActiveGUI(m_iGUISelected, false);
 
467
    if (m_bGUIVisible) {
 
468
        SetActiveGUI(m_iGUISelected);
 
469
    } else {
 
470
        ShowApplication(false);
 
471
        }
 
472
    
 
473
    if(bOpenEventLog) {
 
474
        DisplayEventLog(m_bGUIVisible);
 
475
        m_pFrame->Raise();
 
476
    }
 
477
    
 
478
    return true;
 
479
}
 
480
 
 
481
 
 
482
int CBOINCGUIApp::OnExit() {
 
483
    // Shutdown the System Idle Detection code
 
484
    IdleTrackerDetach();
 
485
 
 
486
    if (m_pDocument) {
 
487
        m_pDocument->OnExit();
 
488
        delete m_pDocument;
 
489
        m_pDocument = NULL;
 
490
    }
 
491
 
 
492
    m_pConfig->SetPath(wxT("/"));
 
493
    if (m_pSkinManager) {
 
494
        m_pConfig->Write(wxT("Skin"), m_pSkinManager->GetSelectedSkin());
 
495
        delete m_pSkinManager;
 
496
    }
 
497
 
 
498
    if (m_pLocale) {
 
499
        delete m_pLocale;
 
500
        m_pLocale = NULL;
 
501
    }
 
502
 
 
503
    if (m_pEventLog) {
 
504
        m_pEventLog->Destroy();
 
505
        m_pEventLog = NULL;
 
506
    }
 
507
 
 
508
 
 
509
    // Save Application State
 
510
    m_pConfig->Write(wxT("AutomaticallyShutdownClient"), m_iShutdownCoreClient);
 
511
    m_pConfig->Write(wxT("DisplayShutdownClientDialog"), m_iDisplayExitDialog);
 
512
    m_pConfig->Write(wxT("DisableAutoStart"), m_iBOINCMGRDisableAutoStart);
 
513
 
 
514
    diagnostics_finish();
 
515
 
 
516
    return wxApp::OnExit();
 
517
}
 
518
 
 
519
 
 
520
///
 
521
/// Pass the command line parameters and discriptions to wxWidgets for displaying.
 
522
///
 
523
void CBOINCGUIApp::OnInitCmdLine(wxCmdLineParser &parser) {
 
524
    wxApp::OnInitCmdLine(parser);
 
525
    static const wxCmdLineEntryDesc cmdLineDesc[] = {
 
526
        { wxCMD_LINE_SWITCH, wxT("a"), wxT("autostart"), _("BOINC Manager was started by the operating system automatically")},
 
527
#if defined(__WXMSW__) || defined(__WXMAC__)
 
528
        { wxCMD_LINE_SWITCH, wxT("s"), wxT("systray"), _("Startup BOINC so only the system tray icon is visible")},
 
529
#else
 
530
        { wxCMD_LINE_OPTION, wxT("e"), wxT("clientdir"), _("Directory containing the BOINC Client executable")},
 
531
        { wxCMD_LINE_OPTION, wxT("d"), wxT("datadir"), _("BOINC data directory")},
 
532
#endif
 
533
        { wxCMD_LINE_OPTION, wxT("n"), wxT("namehost"), _("Host name or IP address")},
 
534
        { wxCMD_LINE_OPTION, wxT("g"), wxT("gui_rpc_port"), _("GUI RPC port number")},
 
535
        { wxCMD_LINE_OPTION, wxT("p"), wxT("password"), _("Password")},
 
536
        { wxCMD_LINE_SWITCH, wxT("b"), wxT("boincargs"), _("Startup BOINC with these optional arguments")},
 
537
        { wxCMD_LINE_SWITCH, wxT("i"), wxT("insecure"), _("disable BOINC security users and permissions")},
 
538
        { wxCMD_LINE_SWITCH, wxT("c"), wxT("checkskins"), _("set skin debugging mode to enable skin manager error messages")},
 
539
        { wxCMD_LINE_SWITCH, wxT("m"), wxT("multiple"), _("multiple instances of BOINC Manager allowed")},
 
540
        { wxCMD_LINE_NONE}  //DON'T forget this line!!
 
541
    };
 
542
    parser.SetDesc(cmdLineDesc);
 
543
}
 
544
 
 
545
 
 
546
///
 
547
/// Parse command line parameters.
 
548
///
 
549
bool CBOINCGUIApp::OnCmdLineParsed(wxCmdLineParser &parser) {
 
550
    // Give default processing (-?, --help and --verbose) the chance to do something.
 
551
    wxApp::OnCmdLineParsed(parser);
 
552
    wxString portNum = wxEmptyString;
 
553
    long longPort;
 
554
    bool hostNameSpecified = false;
 
555
    bool passwordSpecified = false;
 
556
 
 
557
    parser.Found(wxT("boincargs"), &m_strBOINCArguments);
 
558
    if (parser.Found(wxT("autostart"))) {
 
559
        m_bBOINCMGRAutoStarted = true;
 
560
    }
 
561
#if defined(__WXMSW__) || defined(__WXMAC__)
 
562
    if (parser.Found(wxT("systray"))) {
 
563
        m_bGUIVisible = false;
 
564
    }
 
565
#endif
 
566
    if (parser.Found(wxT("insecure"))) {
 
567
        g_use_sandbox = false;
 
568
    }
 
569
    if (parser.Found(wxT("checkskins"))) {
 
570
        m_bDebugSkins = true;
 
571
    }
 
572
    if (parser.Found(wxT("multiple"))) {
 
573
        m_bMultipleInstancesOK = true;
 
574
    }
 
575
 
 
576
#if !(defined(__WXMSW__) || defined(__WXMAC__))
 
577
    if (!parser.Found(wxT("clientdir"), &m_strBOINCMGRRootDirectory)) {
 
578
        m_strBOINCMGRRootDirectory = ::wxGetCwd();
 
579
    }
 
580
    if (m_strBOINCMGRRootDirectory.Last() != '/') {
 
581
        m_strBOINCMGRRootDirectory.Append('/');
 
582
    }
 
583
 
 
584
    if (!parser.Found(wxT("datadir"), &m_strBOINCMGRDataDirectory)) {
 
585
        m_strBOINCMGRDataDirectory = m_strBOINCMGRRootDirectory;
 
586
    }
 
587
    if (m_strBOINCMGRDataDirectory.Last() != '/') {
 
588
        m_strBOINCMGRDataDirectory.Append('/');
 
589
    }
 
590
#endif    
 
591
 
 
592
    if (parser.Found(wxT("namehost"), &m_strHostNameArg)) {
 
593
        hostNameSpecified = true;
 
594
    } else {
 
595
        m_strHostNameArg = wxT("localhost");
 
596
    }
 
597
 
 
598
     if (parser.Found(wxT("gui_rpc_port"), &portNum)) {
 
599
        if (portNum.ToLong(&longPort)) {
 
600
            m_iRPCPortArg = longPort;
 
601
        } else {
 
602
            m_iRPCPortArg = GUI_RPC_PORT;  // conversion failed
 
603
        }
 
604
    } else {
 
605
        m_iRPCPortArg = GUI_RPC_PORT;
 
606
    }
 
607
    
 
608
    if (parser.Found(wxT("password"), &m_strPasswordArg)) {
 
609
        passwordSpecified = true;
 
610
    } else {
 
611
        m_strPasswordArg = wxEmptyString;
 
612
    }
 
613
 
 
614
    if (hostNameSpecified && passwordSpecified) {
 
615
        m_bMultipleInstancesOK = true;
 
616
    }
 
617
    return true;
 
618
}
 
619
 
 
620
 
 
621
///
 
622
/// Detect the desktop that BOINC Manager is running in.
 
623
///
 
624
void CBOINCGUIApp::DetectDisplayInfo() {
 
625
#ifdef __WXMSW__
 
626
    wxChar szWindowStation[256];
 
627
    memset(szWindowStation, 0, sizeof(szWindowStation)/sizeof(wxChar));
 
628
    wxChar szDesktop[256];
 
629
    memset(szDesktop, 0, sizeof(szDesktop)/sizeof(wxChar));
 
630
 
 
631
    if (wxWIN95 != wxGetOsVersion(NULL, NULL)) {
 
632
        // Retrieve the current window station and desktop names
 
633
        GetUserObjectInformation(
 
634
            GetProcessWindowStation(), 
 
635
            UOI_NAME, 
 
636
            szWindowStation,
 
637
            (sizeof(szWindowStation) / sizeof(wxChar)),
 
638
            NULL
 
639
        );
 
640
        GetUserObjectInformation(
 
641
            GetThreadDesktop(GetCurrentThreadId()), 
 
642
            UOI_NAME, 
 
643
            szDesktop,
 
644
            (sizeof(szDesktop) / sizeof(wxChar)),
 
645
            NULL
 
646
        );
 
647
        m_strDefaultWindowStation = szWindowStation;
 
648
        m_strDefaultDesktop = szDesktop;
 
649
    }
 
650
 
 
651
#else
 
652
    wxString p = wxString(getenv("DISPLAY"), wxConvUTF8);
 
653
    if (p) m_strDefaultDisplay = p;
 
654
#endif
 
655
 
 
656
}
 
657
 
 
658
 
 
659
///
 
660
/// Detect if an acessibility aid is running on the system.
 
661
///
 
662
void CBOINCGUIApp::DetectAccessibilityEnabled() {
 
663
#ifdef __WXMSW__
 
664
    BOOL bScreenReaderEnabled = false;
 
665
    SystemParametersInfo(SPI_GETSCREENREADER, NULL, &bScreenReaderEnabled, NULL);
 
666
    m_bAccessibilityEnabled = (bScreenReaderEnabled == TRUE);
 
667
#endif
 
668
}
 
669
 
 
670
 
 
671
///
 
672
/// Detect if another instance of this application is running.
 
673
//  Returns true if there is, otherwise false
 
674
///
 
675
bool CBOINCGUIApp::DetectDuplicateInstance() {
 
676
#ifdef __WXMSW__
 
677
    if (CTaskBarIcon::FireAppRestore()) {
 
678
        return true;
 
679
    }
 
680
#endif
 
681
#ifdef __WXMAC__
 
682
    ProcessSerialNumber PSN;
 
683
    int iInstanceID = wxGetApp().IsAnotherInstanceRunning();
 
684
    if (iInstanceID) {
 
685
        // Bring other instance to the front and exit this instance
 
686
        OSStatus err = GetProcessForPID(iInstanceID, &PSN);
 
687
        if (!err) SetFrontProcess(&PSN);
 
688
        return true;
 
689
    }
 
690
#endif
 
691
    return false;
 
692
}
 
693
 
 
694
 
 
695
///
 
696
/// Determines what name BOINC Manager is called.
 
697
///
 
698
void CBOINCGUIApp::DetectExecutableName() {
 
699
#ifdef __WXMSW__
 
700
    TCHAR   szPath[MAX_PATH-1];
 
701
 
 
702
    // change the current directory to the boinc install directory
 
703
    GetModuleFileName(NULL, szPath, (sizeof(szPath)/sizeof(TCHAR)));
 
704
                
 
705
    TCHAR *pszProg = _tcsrchr(szPath, '\\');
 
706
    if (pszProg) {
 
707
        pszProg++;
 
708
    }
 
709
 
 
710
    // Store the root directory for later use.
 
711
    m_strBOINCMGRExecutableName = pszProg;
 
712
#endif
 
713
}
 
714
 
 
715
 
 
716
///
 
717
/// Determines where the BOINC Manager is executing from.
 
718
///
 
719
void CBOINCGUIApp::DetectRootDirectory() {
 
720
#ifdef __WXMSW__
 
721
    TCHAR   szPath[MAX_PATH-1];
 
722
 
 
723
    // change the current directory to the boinc install directory
 
724
    GetModuleFileName(NULL, szPath, (sizeof(szPath)/sizeof(TCHAR)));
 
725
                
 
726
    TCHAR *pszProg = _tcsrchr(szPath, '\\');
 
727
    if (pszProg) {
 
728
        szPath[pszProg - szPath + 1] = 0;
 
729
    }
 
730
 
 
731
    // Store the root directory for later use.
 
732
    m_strBOINCMGRRootDirectory = szPath;
 
733
#endif
 
734
}
 
735
 
 
736
 
 
737
///
 
738
/// Determines where the BOINC data directory is.
 
739
///
 
740
void CBOINCGUIApp::DetectDataDirectory() {
 
741
#ifdef __WXMSW__
 
742
    //
 
743
    // Determine BOINCMgr Data Directory
 
744
    //
 
745
        LONG    lReturnValue;
 
746
        HKEY    hkSetupHive;
 
747
    LPTSTR  lpszRegistryValue = NULL;
 
748
        DWORD   dwSize = 0;
 
749
 
 
750
    // change the current directory to the boinc data directory if it exists
 
751
        lReturnValue = RegOpenKeyEx(
 
752
        HKEY_LOCAL_MACHINE, 
 
753
        _T("SOFTWARE\\Space Sciences Laboratory, U.C. Berkeley\\BOINC Setup"),
 
754
                0, 
 
755
        KEY_READ,
 
756
        &hkSetupHive
 
757
    );
 
758
    if (lReturnValue == ERROR_SUCCESS) {
 
759
        // How large does our buffer need to be?
 
760
        lReturnValue = RegQueryValueEx(
 
761
            hkSetupHive,
 
762
            _T("DATADIR"),
 
763
            NULL,
 
764
            NULL,
 
765
            NULL,
 
766
            &dwSize
 
767
        );
 
768
        if (lReturnValue != ERROR_FILE_NOT_FOUND) {
 
769
            // Allocate the buffer space.
 
770
            lpszRegistryValue = (LPTSTR) malloc(dwSize);
 
771
            (*lpszRegistryValue) = NULL;
 
772
 
 
773
            // Now get the data
 
774
            lReturnValue = RegQueryValueEx( 
 
775
                hkSetupHive,
 
776
                _T("DATADIR"),
 
777
                NULL,
 
778
                NULL,
 
779
                (LPBYTE)lpszRegistryValue,
 
780
                &dwSize
 
781
            );
 
782
 
 
783
            // Store the root directory for later use.
 
784
            m_strBOINCMGRDataDirectory = lpszRegistryValue;
 
785
        }
 
786
    }
 
787
 
 
788
    // Cleanup
 
789
        if (hkSetupHive) RegCloseKey(hkSetupHive);
 
790
    if (lpszRegistryValue) free(lpszRegistryValue);
 
791
#endif
 
792
#ifdef __WXMAC__
 
793
    m_strBOINCMGRDataDirectory = wxT("/Library/Application Support/BOINC Data");
 
794
#endif
 
795
}
 
796
 
 
797
 
 
798
void CBOINCGUIApp::InitSupportedLanguages() {
 
799
    wxInt32               iIndex = 0;
 
800
    const wxLanguageInfo* liLanguage = NULL;
 
801
 
 
802
    // Prepare the array
 
803
    m_astrLanguages.Insert(wxEmptyString, 0, wxLANGUAGE_USER_DEFINED+1);
 
804
 
 
805
    // These are just special tags so deal with them in a special way
 
806
    m_astrLanguages[wxLANGUAGE_DEFAULT]                    = _("(Automatic Detection)");
 
807
    m_astrLanguages[wxLANGUAGE_UNKNOWN]                    = _("(Unknown)");
 
808
    m_astrLanguages[wxLANGUAGE_USER_DEFINED]               = _("(User Defined)");
 
809
 
 
810
    for (iIndex = 0; iIndex <= wxLANGUAGE_USER_DEFINED; iIndex++) {
 
811
        liLanguage = wxLocale::GetLanguageInfo(iIndex);
 
812
        if (liLanguage) {
 
813
            m_astrLanguages[iIndex] = liLanguage->Description;
 
814
        }
 
815
    }
 
816
}
 
817
 
 
818
 
 
819
int CBOINCGUIApp::IdleTrackerAttach() {
 
820
#ifdef __WXMSW__
 
821
    ::attach_idle_monitor();
 
822
#endif
 
823
    return 0;
 
824
}
 
825
 
 
826
 
 
827
int CBOINCGUIApp::IdleTrackerDetach() {
 
828
#ifdef __WXMSW__
 
829
    ::detach_idle_monitor();
 
830
#endif
 
831
    return 0;
 
832
}
 
833
 
 
834
 
 
835
void CBOINCGUIApp::OnRPCFinished( CRPCFinishedEvent& event ) {
 
836
    CMainDocument*      pDoc = wxGetApp().GetDocument();
 
837
   
 
838
    wxASSERT(pDoc);
 
839
    wxASSERT(wxDynamicCast(pDoc, CMainDocument));
 
840
    
 
841
    pDoc->OnRPCComplete(event);
 
842
}
 
843
 
 
844
 
 
845
int CBOINCGUIApp::UpdateSystemIdleDetection() {
 
846
#ifdef __WXMSW__
 
847
    return get_idle_tick_count();
 
848
#else
 
849
    return TRUE;
 
850
#endif
 
851
}
 
852
 
 
853
 
 
854
int CBOINCGUIApp::StartBOINCScreensaverTest() {
 
855
#ifdef __WXMSW__
 
856
    wxString strExecute = wxEmptyString;
 
857
    wxChar   szExecutableDirectory[4096];
 
858
    memset(szExecutableDirectory, 0, sizeof(szExecutableDirectory));
 
859
 
 
860
    // On Windows the screensaver is located in the Windows directory.
 
861
    GetWindowsDirectory(
 
862
        szExecutableDirectory,
 
863
        (sizeof(szExecutableDirectory) / sizeof(wxChar))
 
864
    );
 
865
 
 
866
    // Append boinc.scr to the end of the strExecute string and get ready to rock
 
867
    strExecute = wxT("\"") + wxString(szExecutableDirectory) + wxT("\\boinc.scr\" /t");
 
868
    ::wxExecute(strExecute);
 
869
#endif
 
870
    return 0;
 
871
}
 
872
 
 
873
 
 
874
int CBOINCGUIApp::StartBOINCDefaultScreensaverTest() {
 
875
#ifdef __WXMSW__
 
876
    wxString strExecute = wxEmptyString;
 
877
    strExecute = wxT("\"") + m_strBOINCMGRRootDirectory + wxT("\\boincscr.exe\" --test");
 
878
    ::wxExecute(strExecute);
 
879
#endif
 
880
    return 0;
 
881
}
 
882
 
 
883
 
 
884
// Display the Event Log, it is a modeless dialog not owned by any
 
885
// other UI element.
 
886
void CBOINCGUIApp::DisplayEventLog(bool bShowWindow) {
 
887
    if (m_pEventLog ) {
 
888
        if (bShowWindow) {
 
889
            m_pEventLog->Raise();
 
890
        }
 
891
    } else {
 
892
        m_pEventLog = new CDlgEventLog();
 
893
        if (m_pEventLog) {
 
894
            m_pEventLog->Show(bShowWindow);
 
895
            if (bShowWindow) {
 
896
                m_pEventLog->Raise();
 
897
            }
 
898
            if (m_pFrame) {
 
899
                m_pFrame->UpdateRefreshTimerInterval();
 
900
            }
 
901
        }
 
902
    }
 
903
}
 
904
 
 
905
 
 
906
void CBOINCGUIApp::OnEventLogClose() {
 
907
    m_pEventLog = NULL;
 
908
    if (m_pFrame) {
 
909
        m_pFrame->UpdateRefreshTimerInterval();
 
910
    }
 
911
}
 
912
 
 
913
    
 
914
// The skin has changed and all UI elements need to reload their bitmaps.
 
915
//
 
916
void CBOINCGUIApp::FireReloadSkin() {
 
917
    if (m_pFrame) {
 
918
            m_pFrame->FireReloadSkin();
 
919
    }
 
920
    if (m_pTaskBarIcon) {
 
921
            m_pTaskBarIcon->FireReloadSkin();
 
922
    }
 
923
}
 
924
 
 
925
 
 
926
bool CBOINCGUIApp::SetActiveGUI(int iGUISelection, bool bShowWindow) {
 
927
    CBOINCBaseFrame* pNewFrame = NULL;
 
928
    CBOINCBaseFrame* pOldFrame = m_pFrame;
 
929
    wxInt32          iTop = 0;
 
930
    wxInt32          iLeft = 0;
 
931
    wxInt32          iHeight = 0;
 
932
    wxInt32          iWidth = 0;
 
933
 
 
934
 
 
935
    // Create the new window
 
936
    if ((iGUISelection != m_iGUISelected) || !m_pFrame) {
 
937
 
 
938
        // Reterieve the desired window state before creating the
 
939
        //   desired frames
 
940
        if (BOINC_ADVANCEDGUI == iGUISelection) {
 
941
            m_pConfig->SetPath(wxT("/"));
 
942
            m_pConfig->Read(wxT("YPos"), &iTop, 30);
 
943
            m_pConfig->Read(wxT("XPos"), &iLeft, 30);
 
944
            m_pConfig->Read(wxT("Width"), &iWidth, 800);
 
945
            m_pConfig->Read(wxT("Height"), &iHeight, 600);
 
946
        } else {
 
947
            m_pConfig->SetPath(wxT("/Simple"));
 
948
            m_pConfig->Read(wxT("YPos"), &iTop, 30);
 
949
            m_pConfig->Read(wxT("XPos"), &iLeft, 30);
 
950
#ifdef __WXMAC__
 
951
            m_pConfig->Read(wxT("Width"), &iWidth, 409);
 
952
            m_pConfig->Read(wxT("Height"), &iHeight, 561);
 
953
#else
 
954
            m_pConfig->Read(wxT("Width"), &iWidth, 416);
 
955
            m_pConfig->Read(wxT("Height"), &iHeight, 570);
 
956
#endif
 
957
        }
 
958
 
 
959
 
 
960
        // Make sure that the new window is going to be visible
 
961
        //   on a screen
 
962
#ifdef __WXMAC__
 
963
        Rect titleRect = {iTop, iLeft, iTop+22, iLeft+iWidth };
 
964
        InsetRect(&titleRect, 5, 5);                // Make sure at least a 5X5 piece visible
 
965
        RgnHandle displayRgn = NewRgn();
 
966
        CopyRgn(GetGrayRgn(), displayRgn);          // Region encompassing all displays
 
967
        Rect menuRect = ((**GetMainDevice())).gdRect;
 
968
        menuRect.bottom = GetMBarHeight() + menuRect.top;
 
969
        RgnHandle menuRgn = NewRgn();
 
970
        RectRgn(menuRgn, &menuRect);                // Region hidden by menu bar
 
971
        DiffRgn(displayRgn, menuRgn, displayRgn);   // Subtract menu bar retion
 
972
        if (!RectInRgn(&titleRect, displayRgn))
 
973
            iTop = iLeft = 30;
 
974
        DisposeRgn(menuRgn);
 
975
        DisposeRgn(displayRgn);
 
976
#else
 
977
            // If either co-ordinate is less then 0 then set it equal to 0 to ensure
 
978
            // it displays on the screen.
 
979
            if ( iLeft < 0 ) iLeft = 30;
 
980
            if ( iTop < 0 ) iTop = 30;
 
981
 
 
982
            // Read the size of the screen
 
983
            wxInt32 iMaxWidth = wxSystemSettings::GetMetric( wxSYS_SCREEN_X );
 
984
            wxInt32 iMaxHeight = wxSystemSettings::GetMetric( wxSYS_SCREEN_Y );
 
985
 
 
986
            // Max sure that it doesn't go off to the right or bottom
 
987
            if ( iLeft + iWidth > iMaxWidth ) iLeft = iMaxWidth - iWidth;
 
988
            if ( iTop + iHeight > iMaxHeight ) iTop = iMaxHeight - iHeight;
 
989
#endif
 
990
 
 
991
        // Create the main window
 
992
        //
 
993
        if (BOINC_ADVANCEDGUI == iGUISelection) {
 
994
            // Initialize the advanced gui window
 
995
            pNewFrame = new CAdvancedFrame(
 
996
                m_pSkinManager->GetAdvanced()->GetApplicationName(), 
 
997
                m_pSkinManager->GetAdvanced()->GetApplicationIcon(),
 
998
                m_pSkinManager->GetAdvanced()->GetApplicationIcon32(),
 
999
                wxPoint(iLeft, iTop),
 
1000
                wxSize(iWidth, iHeight)
 
1001
            );
 
1002
        } else {
 
1003
            // Initialize the simple gui window
 
1004
            pNewFrame = new CSimpleFrame(
 
1005
                m_pSkinManager->GetAdvanced()->GetApplicationName(), 
 
1006
                m_pSkinManager->GetAdvanced()->GetApplicationIcon(),
 
1007
                m_pSkinManager->GetAdvanced()->GetApplicationIcon32(),
 
1008
                wxPoint(iLeft, iTop),
 
1009
                wxSize(iWidth, iHeight)
 
1010
            );
 
1011
        }
 
1012
 
 
1013
        wxASSERT(pNewFrame);
 
1014
 
 
1015
        if (pNewFrame) {
 
1016
            SetTopWindow(pNewFrame);
 
1017
 
 
1018
            // Store the new frame for future use
 
1019
            m_pFrame = pNewFrame;
 
1020
 
 
1021
            // Hide the old one if it exists.  We must do this 
 
1022
            // after updating m_pFrame to prevent Mac OSX from
 
1023
            // hiding the application
 
1024
            if (pOldFrame) pOldFrame->Hide();
 
1025
 
 
1026
            // Delete the old one if it exists
 
1027
            // Note: this has the side effect of hiding the Event Log
 
1028
            if (pOldFrame) pOldFrame->Destroy();
 
1029
 
 
1030
            // Show the new frame if needed (and show the Event Log if open)
 
1031
            if (pNewFrame && bShowWindow) pNewFrame->Show();
 
1032
        }
 
1033
    }
 
1034
 
 
1035
    // Show the new frame if needed 
 
1036
    if (m_pFrame && !m_pFrame->IsShown() && bShowWindow) {
 
1037
        m_pFrame->Show();
 
1038
        m_pFrame->Raise();
 
1039
#ifdef __WXMSW__
 
1040
        ::SetForegroundWindow((HWND)m_pFrame->GetHWND());
 
1041
#endif
 
1042
    }
 
1043
 
 
1044
    // Raise the frame to the top of the Z order if needed
 
1045
    if (m_pFrame && m_pFrame->IsShown() && bShowWindow) {
 
1046
        m_pFrame->Raise();
 
1047
#ifdef __WXMSW__
 
1048
        ::SetForegroundWindow((HWND)m_pFrame->GetHWND());
 
1049
#endif
 
1050
    }
 
1051
 
 
1052
    m_iGUISelected = iGUISelection;
 
1053
    m_pConfig->SetPath(wxT("/"));
 
1054
    m_pConfig->Write(wxT("GUISelection"), iGUISelection);
 
1055
 
 
1056
    return true;
 
1057
}
 
1058
 
 
1059
 
 
1060
int CBOINCGUIApp::ConfirmExit() {
 
1061
    CSkinAdvanced*  pSkinAdvanced = wxGetApp().GetSkinManager()->GetAdvanced();
 
1062
    CMainDocument*  pDoc = wxGetApp().GetDocument();
 
1063
    wxString        strConnectedCompter = wxEmptyString;
 
1064
    bool            bWasVisible;
 
1065
    int             retval = 0;
 
1066
 
 
1067
    wxASSERT(pDoc);
 
1068
    wxASSERT(pSkinAdvanced);
 
1069
    wxASSERT(wxDynamicCast(pDoc, CMainDocument));
 
1070
    wxASSERT(wxDynamicCast(pSkinAdvanced, CSkinAdvanced));
 
1071
    
 
1072
    pDoc->GetConnectedComputerName(strConnectedCompter);
 
1073
    if (!pDoc->IsComputerNameLocal(strConnectedCompter)) {
 
1074
        // Don't shut down remote clients on Manager exit
 
1075
        return 1;
 
1076
    }
 
1077
 
 
1078
    // Don't run confirmation dialog if logging out or shutting down Mac, 
 
1079
    // or if emergency exit from AsyncRPCDlg
 
1080
    if (s_bSkipExitConfirmation)
 
1081
        return 1;
 
1082
 
 
1083
#ifndef __WXMSW__
 
1084
    if (!m_iDisplayExitDialog) {
 
1085
        return 1;   // User doesn't want to display the dialog and wants to shutdown the client.
 
1086
    }
 
1087
#else
 
1088
    if (!m_iDisplayExitDialog) {
 
1089
                return 1;   // User doesn't want to display the dialog and just wants to use their previous value
 
1090
        }
 
1091
#endif
 
1092
 
 
1093
    bWasVisible = IsApplicationVisible();
 
1094
    ShowApplication(true);
 
1095
 
 
1096
    CDlgExitMessage dlg(NULL);
 
1097
 
 
1098
    if (!pSkinAdvanced->GetExitMessage().IsEmpty()) {
 
1099
        dlg.m_DialogExitMessage->SetLabel(pSkinAdvanced->GetExitMessage());
 
1100
    }
 
1101
 
 
1102
#ifdef __WXMSW__
 
1103
    if (m_iShutdownCoreClient) {
 
1104
        dlg.m_DialogShutdownCoreClient->SetValue(TRUE);
 
1105
    }
 
1106
#endif
 
1107
 
 
1108
    if (m_iDisplayExitDialog) {
 
1109
        dlg.m_DialogDisplay->SetValue(FALSE);
 
1110
    }
 
1111
 
 
1112
    dlg.Fit();
 
1113
    dlg.Centre();
 
1114
 
 
1115
    if (wxID_OK == dlg.ShowModal()) {
 
1116
#ifndef __WXMSW__
 
1117
        s_bSkipExitConfirmation = true;     // Don't ask twice (only affects Mac)
 
1118
#else
 
1119
        m_iShutdownCoreClient = dlg.m_DialogShutdownCoreClient->GetValue();
 
1120
#endif
 
1121
        m_iDisplayExitDialog = !dlg.m_DialogDisplay->GetValue();
 
1122
        retval = true;
 
1123
 
 
1124
    }
 
1125
 
 
1126
    if (!bWasVisible) {
 
1127
        ShowApplication(false);
 
1128
    }
 
1129
 
 
1130
    return retval;       // User cancelled exit
 
1131
}
 
1132
 
 
1133
 
 
1134
// Use this instead of wxMessageBox from all tab Views to suppress 
 
1135
// Periodic RPCs.  See comment in CMainDocument::RunPeriodicRPCs()
 
1136
// for a fuller explanation.
 
1137
int CBOINCGUIApp::SafeMessageBox(const wxString& message, const wxString& caption, long style,
 
1138
                 wxWindow *parent, int x, int y )
 
1139
{
 
1140
    int retval;
 
1141
    
 
1142
    m_bSafeMessageBoxDisplayed++;
 
1143
    
 
1144
    retval = wxMessageBox(message, caption, style, parent, x, y);
 
1145
 
 
1146
    m_bSafeMessageBoxDisplayed--;
 
1147
 
 
1148
    return retval;
 
1149
}
 
1150
 
 
1151
 
 
1152
///
 
1153
/// Determines if another instance of BOINC Manager is running.
 
1154
///
 
1155
/// @return
 
1156
///  true if another instance of BOINC Manager is running, otherwise false.
 
1157
///
 
1158
/// Note: will always return false on Win95, Win98, WinME
 
1159
/// 
 
1160
int CBOINCGUIApp::IsAnotherInstanceRunning() {
 
1161
    std::vector<PROCINFO> piv;
 
1162
    PROCINFO* pi;
 
1163
    int retval;
 
1164
    char myName[256];
 
1165
    int otherInstanceID = 0;
 
1166
    int myPid;
 
1167
 
 
1168
    // Look for BOINC Manager in list of all running processes
 
1169
    retval = procinfo_setup(piv);
 
1170
    if (retval) return false;     // Should never happen
 
1171
 
 
1172
#ifdef _WIN32
 
1173
    myPid = (int)GetCurrentProcessId();
 
1174
#else
 
1175
    myPid = getpid();
 
1176
#endif
 
1177
 
 
1178
    // Get the name of this Application
 
1179
    myName[0] = 0;
 
1180
    for (unsigned int i=0; i<piv.size(); i++) {
 
1181
        pi = &(piv[i]);
 
1182
        if (pi->id == myPid) {
 
1183
            strncpy(myName, pi->command, sizeof(myName));
 
1184
            break;
 
1185
        }
 
1186
    }
 
1187
 
 
1188
    if (myName[0] == 0) {
 
1189
         return false;     // Should never happen
 
1190
    }
 
1191
    
 
1192
    // Search process list for other applications with same name
 
1193
    for (unsigned int i=0; i<piv.size(); i++) {
 
1194
        pi = &(piv[i]);
 
1195
        if (pi->id == myPid) continue;
 
1196
        if (!strcmp(pi->command, myName)) {
 
1197
            otherInstanceID = pi->id;
 
1198
            break;
 
1199
        }
 
1200
    }
 
1201
    
 
1202
    return otherInstanceID;
 
1203
}
 
1204
 
 
1205
 
 
1206
///
 
1207
/// Determines if the current process is visible.
 
1208
///
 
1209
/// @return
 
1210
///  true if the current process is visible, otherwise false.
 
1211
/// 
 
1212
bool CBOINCGUIApp::IsApplicationVisible() {
 
1213
#ifdef __WXMAC__
 
1214
    if (IsProcessVisible(&m_psnCurrentProcess)) {
 
1215
        return true;
 
1216
    }
 
1217
#endif
 
1218
    return false;
 
1219
}
 
1220
 
 
1221
///
 
1222
/// Shows or hides the current process.
 
1223
///
 
1224
/// @param bShow
 
1225
///   true will show the process, false will hide the process.
 
1226
///
 
1227
#ifdef __WXMAC__
 
1228
void CBOINCGUIApp::ShowApplication(bool bShow) {
 
1229
    if (bShow) {
 
1230
        SetFrontProcess(&m_psnCurrentProcess);
 
1231
    } else {
 
1232
        ShowHideProcess(&m_psnCurrentProcess, false);
 
1233
    }
 
1234
}
 
1235
#else
 
1236
void CBOINCGUIApp::ShowApplication(bool) {
 
1237
}
 
1238
#endif
 
1239
 
 
1240
 
 
1241
bool CBOINCGUIApp::ShowInterface() {
 
1242
    return SetActiveGUI(m_iGUISelected, true);
 
1243
}
 
1244
 
 
1245
 
 
1246
bool CBOINCGUIApp::ShowNotifications() {
 
1247
    bool retval = false;
 
1248
 
 
1249
    retval = SetActiveGUI(m_iGUISelected, true);
 
1250
    if (retval) {
 
1251
        GetFrame()->FireNotification();
 
1252
        GetDocument()->UpdateUnreadNoticeState();
 
1253
    }
 
1254
 
 
1255
    return retval;
 
1256
}
 
1257
 
 
1258
 
 
1259
bool CBOINCGUIApp::IsModalDialogDisplayed() {
 
1260
    if (m_bSafeMessageBoxDisplayed) return true;
 
1261
    
 
1262
    // Search for the dialog by ID since all of BOINC Manager's 
 
1263
    // dialog IDs are 10000.
 
1264
    if (wxDynamicCast(wxWindow::FindWindowById(ID_ANYDIALOG), wxDialog)) {
 
1265
        return true;
 
1266
    }
 
1267
    
 
1268
    if (m_pDocument) {
 
1269
        if (m_pDocument->WaitingForRPC()) {
 
1270
            return true;
 
1271
        }
 
1272
    }
 
1273
    return false;
 
1274
}
 
1275
 
 
1276
void CBOINCGUIApp::DeleteTaskBarIcon() {
 
1277
    if (m_pTaskBarIcon) {
 
1278
        delete m_pTaskBarIcon;
 
1279
    }
 
1280
    m_pTaskBarIcon = NULL;
 
1281
}
 
1282
 
 
1283
#ifdef __WXMAC__
 
1284
void CBOINCGUIApp::DeleteMacSystemMenu() {
 
1285
    if (m_pMacSystemMenu) {
 
1286
        delete m_pMacSystemMenu;
 
1287
    }
 
1288
    m_pMacSystemMenu = NULL;
 
1289
}
 
1290
#endif
 
1291
 
 
1292
 
 
1293
// Prevent recursive entry of CMainDocument::RequestRPC()
 
1294
int CBOINCGUIApp::FilterEvent(wxEvent &event) {
 
1295
    if (!m_pDocument) return -1;
 
1296
    if (!m_pDocument->WaitingForRPC()) return -1;
 
1297
 
 
1298
    // If in RPC Please Wait dialog, reject all command 
 
1299
    // and timer events except: 
 
1300
    //  - RPC Finished
 
1301
    //  - those for that dialog or its children
 
1302
    //  - Open Manager menu item from system tray icon
 
1303
    int theEventType = event.GetEventType();
 
1304
 
 
1305
    if ((theEventType == wxEVT_COMMAND_MENU_SELECTED) && (event.GetId() == wxID_OPEN)) {
 
1306
        return -1;        
 
1307
    }
 
1308
 
 
1309
    wxDialog* theRPCWaitDialog = m_pDocument->GetRPCWaitDialog();
 
1310
    wxObject* theObject = event.GetEventObject();
 
1311
    while (theObject) {
 
1312
        if (!theObject->IsKindOf(CLASSINFO(wxWindow))) break;
 
1313
        if (theObject == theRPCWaitDialog) return -1;
 
1314
        theObject = ((wxWindow*)theObject)->GetParent();
 
1315
    }
 
1316
    
 
1317
    // Allow all except Command, Timer and Mouse Moved events
 
1318
    if (event.IsCommandEvent()) {
 
1319
        return false;
 
1320
    }
 
1321
    
 
1322
    if (theEventType == wxEVT_TIMER) {
 
1323
        return false;
 
1324
    }
 
1325
    
 
1326
#ifdef __WXMSW__
 
1327
    if (theEventType == wxEVT_TASKBAR_MOVE) {
 
1328
        return false;
 
1329
    }
 
1330
#endif
 
1331
   
 
1332
    return -1;
 
1333
}
 
1334