2005-01-20 23:22:22 +00:00
// Berkeley Open Infrastructure for Network Computing
// http://boinc.berkeley.edu
// Copyright (C) 2005 University of California
2004-11-14 08:29:32 +00:00
//
2005-01-20 23:22:22 +00:00
// This is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation;
// either version 2.1 of the License, or (at your option) any later version.
2004-01-18 19:36:50 +00:00
//
2005-01-20 23:22:22 +00:00
// This software is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Lesser General Public License for more details.
//
// To view the GNU Lesser General Public License visit
// http://www.gnu.org/copyleft/lesser.html
// or write to the Free Software Foundation, Inc.,
2007-10-09 11:35:47 +00:00
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2005-03-23 00:16:58 +00:00
//
// Contributor(s):
// DirectX 8.1 Screen Saver Framework from Microsoft.
// Microsoft Knowledge Base Article - 79212
//
2003-06-15 20:28:30 +00:00
2004-06-16 23:29:48 +00:00
# include "boinc_win.h"
# include <windowsx.h>
# include <mmsystem.h>
# include <regstr.h>
# include <strsafe.h>
2007-10-05 13:28:11 +00:00
# include <mmsystem.h>
# define COMPILE_MULTIMON_STUBS
2004-06-16 23:29:48 +00:00
2004-11-15 06:44:50 +00:00
# include "boinc_ss.h"
2006-06-14 07:14:09 +00:00
# include "diagnostics.h"
2006-09-01 21:38:18 +00:00
# include "common_defs.h"
2006-05-16 21:14:18 +00:00
# include "util.h"
2007-08-14 17:23:30 +00:00
# include "gui_rpc_client.h"
# include "screensaver.h"
2007-08-13 19:57:18 +00:00
# include "screensaver_win.h"
2004-03-04 11:41:43 +00:00
2005-07-07 22:26:49 +00:00
# ifdef _DEBUG
# define UNUSED(x)
# else
# define UNUSED(x) x
# endif
2002-11-14 00:49:24 +00:00
2006-04-13 00:28:31 +00:00
static HMODULE gshUser32 = NULL ;
static HMODULE gshPasswordCPL = NULL ;
static VERIFYPWDPROC gspfnMyVerifyPwdProc = NULL ;
2006-04-12 02:28:50 +00:00
static MYGETLASTINPUTINFO gspfnMyGetLastInputInfo = NULL ;
static MYISHUNGAPPWINDOW gspfnMyIsHungAppWindow = NULL ;
static MYBROADCASTSYSTEMMESSAGE gspfnMyBroadcastSystemMessage = NULL ;
static CScreensaver * gspScreensaver = NULL ;
2004-12-19 04:27:02 +00:00
2006-12-28 18:31:32 +00:00
const UINT WM_SETTIMER = RegisterWindowMessage ( TEXT ( " BOINCSetTimer " ) ) ;
const UINT WM_INTERRUPTSAVER = RegisterWindowMessage ( TEXT ( " BOINCInterruptScreensaver " ) ) ;
2006-04-13 00:28:31 +00:00
const UINT WM_BOINCSFW = RegisterWindowMessage ( TEXT ( " BOINCSetForegroundWindow " ) ) ;
2004-12-19 04:27:02 +00:00
2002-12-16 22:34:50 +00:00
2005-04-06 23:12:27 +00:00
INT WINAPI WinMain (
2005-07-07 22:26:49 +00:00
HINSTANCE hInstance , HINSTANCE UNUSED ( hPrevInstance ) , LPSTR UNUSED ( lpCmdLine ) , int UNUSED ( nCmdShow )
2005-04-06 23:12:27 +00:00
) {
2004-11-14 08:29:32 +00:00
HRESULT hr ;
2006-04-12 02:28:50 +00:00
CScreensaver BOINCSS ;
2004-11-14 08:29:32 +00:00
int retval ;
WSADATA wsdata ;
2006-04-12 02:28:50 +00:00
BOOL bIs95 = FALSE ;
2006-04-13 00:28:31 +00:00
BOOL bIs9x = FALSE ;
DWORD dwVal ;
DWORD dwSize = sizeof ( dwVal ) ;
HKEY hKey ;
2007-01-11 05:10:26 +00:00
# ifdef _DEBUG
2006-06-14 07:14:09 +00:00
// Initialize Diagnostics
2006-04-12 04:27:22 +00:00
retval = diagnostics_init (
2004-12-19 04:27:02 +00:00
BOINC_DIAG_DUMPCALLSTACKENABLED |
BOINC_DIAG_HEAPCHECKENABLED |
BOINC_DIAG_MEMORYLEAKCHECKENABLED |
2006-06-14 07:14:09 +00:00
BOINC_DIAG_ARCHIVESTDOUT |
BOINC_DIAG_REDIRECTSTDOUTOVERWRITE |
BOINC_DIAG_REDIRECTSTDERROVERWRITE |
BOINC_DIAG_TRACETOSTDOUT ,
2006-04-12 04:27:22 +00:00
" stdoutscr " ,
" stderrscr "
2006-06-14 07:14:09 +00:00
) ;
2005-04-06 22:53:00 +00:00
if ( retval ) {
2005-02-12 08:14:00 +00:00
BOINCTRACE ( " WinMain - BOINC Screensaver Diagnostic Error '%d' \n " , retval ) ;
2004-12-19 04:27:02 +00:00
MessageBox ( NULL , NULL , " BOINC Screensaver Diagnostic Error " , MB_OK ) ;
2004-11-13 07:11:40 +00:00
}
2007-01-11 05:10:26 +00:00
# endif
2004-11-13 07:11:40 +00:00
2006-04-12 02:28:50 +00:00
// Figure out if we're on Win9x
OSVERSIONINFO osvi ;
osvi . dwOSVersionInfoSize = sizeof ( osvi ) ;
GetVersionEx ( & osvi ) ;
2006-04-13 00:28:31 +00:00
bIs9x = osvi . dwPlatformId = = VER_PLATFORM_WIN32_WINDOWS ;
2006-04-12 02:28:50 +00:00
bIs95 = ( osvi . dwPlatformId = = VER_PLATFORM_WIN32_WINDOWS ) & &
( ( osvi . dwMajorVersion = = 4 ) & & ( osvi . dwMinorVersion = = 0 ) ) ;
// Load dynamically linked modules
gshUser32 = LoadLibrary ( _T ( " USER32.DLL " ) ) ;
2006-04-13 00:28:31 +00:00
if ( bIs9x ) {
gshPasswordCPL = LoadLibrary ( _T ( " PASSWORD.CPL " ) ) ;
}
2006-04-12 02:28:50 +00:00
// Map function pointers
if ( gshUser32 ) {
gspfnMyGetLastInputInfo = ( MYGETLASTINPUTINFO ) GetProcAddress ( gshUser32 , _T ( " GetLastInputInfo " ) ) ;
gspfnMyIsHungAppWindow = ( MYISHUNGAPPWINDOW ) GetProcAddress ( gshUser32 , _T ( " IsHungAppWindow " ) ) ;
if ( bIs95 ) {
gspfnMyBroadcastSystemMessage = ( MYBROADCASTSYSTEMMESSAGE ) GetProcAddress ( gshUser32 , _T ( " BroadcastSystemMessage " ) ) ;
} else {
gspfnMyBroadcastSystemMessage = ( MYBROADCASTSYSTEMMESSAGE ) GetProcAddress ( gshUser32 , _T ( " BroadcastSystemMessageA " ) ) ;
}
}
2006-04-13 00:28:31 +00:00
if ( gshPasswordCPL ) {
if ( RegOpenKey ( HKEY_CURRENT_USER , REGSTR_PATH_SCREENSAVE , & hKey ) = = ERROR_SUCCESS ) {
if ( ( RegQueryValueEx ( hKey , REGSTR_VALUE_USESCRPASSWORD , NULL , NULL , ( BYTE * ) & dwVal , & dwSize ) = = ERROR_SUCCESS ) & & dwVal ) {
gspfnMyVerifyPwdProc = ( VERIFYPWDPROC ) GetProcAddress ( gshPasswordCPL , _T ( " VerifyScreenSavePwd " ) ) ;
RegCloseKey ( hKey ) ;
}
}
}
2006-04-12 02:28:50 +00:00
2007-08-28 18:54:31 +00:00
// Initialize the CRT random number generator.
srand ( ( unsigned int ) time ( 0 ) ) ;
// Initialize the Windows sockets interface.
2005-04-06 23:12:27 +00:00
retval = WSAStartup ( MAKEWORD ( 1 , 1 ) , & wsdata ) ;
if ( retval ) {
2005-02-12 08:14:00 +00:00
BOINCTRACE ( " WinMain - Winsock Initialization Failure '%d' \n " , retval ) ;
2004-11-14 08:29:32 +00:00
return retval ;
}
2005-04-06 23:12:27 +00:00
if ( FAILED ( hr = BOINCSS . Create ( hInstance ) ) ) {
BOINCSS . DisplayErrorMsg ( hr ) ;
2004-11-14 08:29:32 +00:00
WSACleanup ( ) ;
2004-01-17 21:34:54 +00:00
return 0 ;
}
2006-04-12 02:28:50 +00:00
2004-11-14 08:29:32 +00:00
retval = BOINCSS . Run ( ) ;
2006-04-12 02:28:50 +00:00
2007-08-28 18:54:31 +00:00
// Cleanup the Windows sockets interface.
2004-11-14 08:29:32 +00:00
WSACleanup ( ) ;
2006-04-12 02:28:50 +00:00
// Clean up function pointers.
gspfnMyGetLastInputInfo = NULL ;
gspfnMyIsHungAppWindow = NULL ;
gspfnMyBroadcastSystemMessage = NULL ;
2006-04-13 00:28:31 +00:00
gspfnMyVerifyPwdProc = NULL ;
2006-04-12 02:28:50 +00:00
// Free modules
FreeLibrary ( gshUser32 ) ;
2006-04-13 00:28:31 +00:00
if ( gshPasswordCPL ) {
FreeLibrary ( gshPasswordCPL ) ;
gshPasswordCPL = NULL ;
}
2006-04-12 02:28:50 +00:00
2004-11-14 08:29:32 +00:00
return retval ;
2004-01-17 21:34:54 +00:00
}
2002-12-16 22:34:50 +00:00
2002-11-18 21:20:54 +00:00
2005-04-06 23:12:27 +00:00
CScreensaver : : CScreensaver ( ) {
2006-04-12 02:28:50 +00:00
gspScreensaver = this ;
2003-10-22 18:39:22 +00:00
2004-01-17 21:34:54 +00:00
m_bCheckingSaverPassword = FALSE ;
m_bIs9x = FALSE ;
m_dwSaverMouseMoveCount = 0 ;
m_hWnd = NULL ;
m_hWndParent = NULL ;
m_bAllScreensSame = FALSE ;
m_bWindowed = FALSE ;
m_bWaitForInputIdle = FALSE ;
m_bErrorMode = FALSE ;
m_hrError = S_OK ;
2004-11-16 08:06:11 +00:00
m_szError [ 0 ] = _T ( ' \0 ' ) ;
2004-01-17 21:34:54 +00:00
2005-04-06 23:12:27 +00:00
LoadString ( NULL , IDS_DESCRIPTION , m_strWindowTitle , 200 ) ;
2004-01-17 21:34:54 +00:00
2007-10-09 10:01:27 +00:00
m_bPaintingInitialized = FALSE ;
2005-02-09 21:54:04 +00:00
m_dwBlankScreen = 0 ;
2005-02-03 19:11:35 +00:00
m_dwBlankTime = 0 ;
2004-01-17 21:34:54 +00:00
2007-10-09 10:01:27 +00:00
rpc = NULL ;
2007-08-14 17:23:30 +00:00
m_hDataManagementThread = NULL ;
m_hGraphicsApplication = NULL ;
m_bResetCoreState = TRUE ;
2007-10-09 10:01:27 +00:00
m_QuitDataManagementProc = FALSE ;
2004-12-03 19:47:54 +00:00
m_bBOINCConfigChecked = FALSE ;
m_bBOINCStartupConfigured = FALSE ;
2007-09-26 10:17:43 +00:00
memset ( & m_running_result , 0 , sizeof ( m_running_result ) ) ;
2004-12-03 19:47:54 +00:00
2007-10-09 10:01:27 +00:00
ZeroMemory ( m_Monitors , sizeof ( m_Monitors ) ) ;
2004-01-17 21:34:54 +00:00
m_dwNumMonitors = 0 ;
2006-04-12 02:28:50 +00:00
m_dwLastInputTimeAtStartup = 0 ;
2007-10-05 13:28:11 +00:00
m_tThreadCreateTime = 0 ;
2004-01-17 21:34:54 +00:00
}
2005-04-06 23:12:27 +00:00
// Have the client program call this function before calling Run().
//
HRESULT CScreensaver : : Create ( HINSTANCE hInstance ) {
2004-01-17 21:34:54 +00:00
HRESULT hr ;
2005-02-03 19:11:35 +00:00
BOOL bReturnValue ;
2002-12-16 22:34:50 +00:00
2004-01-17 21:34:54 +00:00
m_hInstance = hInstance ;
// Parse the command line and do the appropriate thing
2005-04-06 23:12:27 +00:00
m_SaverMode = ParseCommandLine ( GetCommandLine ( ) ) ;
2004-01-17 21:34:54 +00:00
2004-11-13 07:11:40 +00:00
// Figure out if we're on Win9x
OSVERSIONINFO osvi ;
osvi . dwOSVersionInfoSize = sizeof ( osvi ) ;
2005-04-06 23:12:27 +00:00
GetVersionEx ( & osvi ) ;
2004-11-13 07:11:40 +00:00
m_bIs9x = ( osvi . dwPlatformId = = VER_PLATFORM_WIN32_WINDOWS ) ;
2006-04-12 02:28:50 +00:00
// Store last input value if it exists
if ( gspfnMyGetLastInputInfo ) {
LASTINPUTINFO lii ;
lii . cbSize = sizeof ( LASTINPUTINFO ) ;
gspfnMyGetLastInputInfo ( & lii ) ;
m_dwLastInputTimeAtStartup = lii . dwTime ;
}
2002-12-16 22:34:50 +00:00
2004-11-14 08:29:32 +00:00
// Enumerate Monitors
EnumMonitors ( ) ;
2004-01-17 21:34:54 +00:00
2005-02-09 21:54:04 +00:00
// Retrieve the blank screen flag so we can determine if we are
// suppose to actually blank the screen at some point.
2005-04-06 23:12:27 +00:00
bReturnValue = UtilGetRegKey ( REG_BLANK_NAME , m_dwBlankScreen ) ;
2005-02-12 08:14:00 +00:00
BOINCTRACE ( " CScreensaver::Create - Get Reg Key REG_BLANK_NAME return value '%d' \n " , bReturnValue ) ;
2005-04-06 23:12:27 +00:00
if ( bReturnValue ! = 0 ) m_dwBlankScreen = 0 ;
2005-02-09 21:54:04 +00:00
2005-02-03 19:11:35 +00:00
// Retrieve the blank screen timeout
// make sure you check return value of registry queries
// in case the item in question doesn't happen to exist.
2005-04-06 23:12:27 +00:00
bReturnValue = UtilGetRegKey ( REG_BLANK_TIME , m_dwBlankTime ) ;
2005-02-12 08:14:00 +00:00
BOINCTRACE ( " CScreensaver::Create - Get Reg Key REG_BLANK_TIME return value '%d' \n " , bReturnValue ) ;
2005-04-06 23:12:27 +00:00
if ( bReturnValue ! = 0 ) m_dwBlankTime = 5 ;
2005-02-03 19:11:35 +00:00
2005-02-04 02:54:25 +00:00
// Save the value back to the registry in case this is the first
// execution and so we need the default value later.
2005-04-06 23:12:27 +00:00
bReturnValue = UtilSetRegKey ( REG_BLANK_NAME , m_dwBlankScreen ) ;
2005-02-12 08:14:00 +00:00
BOINCTRACE ( " CScreensaver::Create - Set Reg Key REG_BLANK_NAME return value '%d' \n " , bReturnValue ) ;
2005-04-06 23:12:27 +00:00
bReturnValue = UtilSetRegKey ( REG_BLANK_TIME , m_dwBlankTime ) ;
2005-02-12 08:14:00 +00:00
BOINCTRACE ( " CScreensaver::Create - Set Reg Key REG_BLANK_TIME return value '%d' \n " , bReturnValue ) ;
2005-02-04 02:54:25 +00:00
2005-02-04 17:29:59 +00:00
// Calculate the estimated blank time by adding the current time
// and and the user specified time which is in minutes
2005-07-06 09:14:43 +00:00
m_dwBlankTime = ( DWORD ) time ( 0 ) + ( m_dwBlankTime * 60 ) ;
2005-02-04 17:29:59 +00:00
2005-04-05 10:23:15 +00:00
// Create the infrastructure mutexes so we can properly aquire them to report
// errors
2005-04-06 23:12:27 +00:00
if ( ! CreateInfrastructureMutexes ( ) ) {
2005-04-05 10:23:15 +00:00
return E_FAIL ;
2005-04-06 23:12:27 +00:00
}
2005-04-05 10:23:15 +00:00
2007-10-05 13:28:11 +00:00
if ( rpc = = NULL ) rpc = new RPC_CLIENT ;
// Create the screen saver window(s)
2005-04-06 23:12:27 +00:00
if ( m_SaverMode = = sm_preview | |
m_SaverMode = = sm_full
) {
if ( FAILED ( hr = CreateSaverWindow ( ) ) ) {
SetError ( TRUE , hr ) ;
}
2004-01-17 21:34:54 +00:00
}
2005-04-06 23:12:27 +00:00
if ( m_SaverMode = = sm_preview ) {
2004-01-17 21:34:54 +00:00
// In preview mode, "pause" (enter a limited message loop) briefly
// before proceeding, so the display control panel knows to update itself.
m_bWaitForInputIdle = TRUE ;
// Post a message to mark the end of the initial group of window messages
2006-04-13 04:21:23 +00:00
PostMessage ( m_hWnd , WM_SETTIMER , 0 , 0 ) ;
2004-01-17 21:34:54 +00:00
MSG msg ;
2005-04-06 23:12:27 +00:00
while ( m_bWaitForInputIdle ) {
2004-01-17 21:34:54 +00:00
// If GetMessage returns FALSE, it's quitting time.
2005-04-06 23:12:27 +00:00
if ( ! GetMessage ( & msg , m_hWnd , 0 , 0 ) ) {
2004-01-17 21:34:54 +00:00
// Post the quit message to handle it later
PostQuitMessage ( 0 ) ;
break ;
}
2005-04-06 23:12:27 +00:00
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
2004-01-17 21:34:54 +00:00
}
}
return S_OK ;
}
2005-04-06 23:12:27 +00:00
// Starts main execution of the screen saver.
//
INT CScreensaver : : Run ( ) {
2007-12-14 19:38:42 +00:00
HOST_INFO hostinfo ;
2004-01-17 21:34:54 +00:00
HRESULT hr ;
// Parse the command line and do the appropriate thing
2005-04-06 23:12:27 +00:00
switch ( m_SaverMode ) {
case sm_config :
if ( m_bErrorMode ) {
DisplayErrorMsg ( m_hrError ) ;
} else {
DoConfig ( ) ;
2004-01-17 21:34:54 +00:00
}
2005-04-06 23:12:27 +00:00
break ;
2007-12-14 18:26:24 +00:00
case sm_test :
2007-12-14 19:38:42 +00:00
rpc - > init ( NULL ) ;
rpc - > get_host_info ( hostinfo ) ;
rpc - > close ( ) ;
2007-12-14 18:26:24 +00:00
break ;
2006-05-02 07:53:28 +00:00
case sm_preview :
2008-05-15 21:39:40 +00:00
// In Windows, preview mode is for the mini-view of the screensaver.
// For BOINC we just display the icon, so there is no need to
// startup the data management thread which in turn will
// launch a graphics application.
if ( FAILED ( hr = DoSaver ( ) ) ) {
DisplayErrorMsg ( hr ) ;
}
break ;
2005-04-06 23:12:27 +00:00
case sm_full :
2006-04-13 08:37:25 +00:00
// Create the data management thread to talk with the daemon
if ( ! CreateDataManagementThread ( ) ) {
return E_FAIL ;
}
2005-04-06 23:12:27 +00:00
if ( FAILED ( hr = DoSaver ( ) ) ) {
DisplayErrorMsg ( hr ) ;
2004-01-17 21:34:54 +00:00
}
2006-04-13 08:37:25 +00:00
// Create the data management thread to talk with the daemon
//
2007-10-09 10:01:27 +00:00
if ( ! DestroyDataManagementThread ( ) ) {
2006-04-13 08:37:25 +00:00
return E_FAIL ;
}
2007-10-09 10:01:27 +00:00
if ( rpc ) {
delete rpc ;
rpc = NULL ;
}
2005-04-06 23:12:27 +00:00
break ;
case sm_passwordchange :
ChangePassword ( ) ;
break ;
2004-01-17 21:34:54 +00:00
}
2005-04-05 10:23:15 +00:00
return 0 ;
2004-01-17 21:34:54 +00:00
}
2005-04-06 23:12:27 +00:00
// Displays error messages in a message box
//
HRESULT CScreensaver : : DisplayErrorMsg ( HRESULT hr ) {
2005-04-05 10:23:15 +00:00
TCHAR strMsg [ 512 ] ;
2004-11-14 08:29:32 +00:00
2005-04-06 23:12:27 +00:00
GetTextForError ( hr , strMsg , 512 ) ;
2005-04-05 10:23:15 +00:00
2005-04-06 23:12:27 +00:00
MessageBox ( m_hWnd , strMsg , m_strWindowTitle , MB_ICONERROR | MB_OK ) ;
2005-04-05 10:23:15 +00:00
return hr ;
2004-01-17 21:34:54 +00:00
}
2005-04-06 23:12:27 +00:00
// Interpret command-line parameters passed to this app.
//
SaverMode CScreensaver : : ParseCommandLine ( TCHAR * pstrCommandLine ) {
2004-01-17 21:34:54 +00:00
m_hWndParent = NULL ;
2004-11-13 07:11:40 +00:00
BOINCTRACE ( " ParseCommandLine: '%s' \n " , pstrCommandLine ) ;
2004-01-17 21:34:54 +00:00
// Skip the first part of the command line, which is the full path
// to the exe. If it contains spaces, it will be contained in quotes.
2005-04-06 23:12:27 +00:00
if ( * pstrCommandLine = = _T ( ' \" ' ) ) {
2004-01-17 21:34:54 +00:00
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
while ( * pstrCommandLine ! = _T ( ' \0 ' ) & & * pstrCommandLine ! = _T ( ' \" ' ) ) {
2004-01-17 21:34:54 +00:00
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
}
if ( * pstrCommandLine = = _T ( ' \" ' ) ) {
2004-01-17 21:34:54 +00:00
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
}
} else {
while ( * pstrCommandLine ! = _T ( ' \0 ' ) & & * pstrCommandLine ! = _T ( ' ' ) ) {
2004-01-17 21:34:54 +00:00
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
}
if ( * pstrCommandLine = = _T ( ' ' ) ) {
2004-01-17 21:34:54 +00:00
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
}
2004-01-17 21:34:54 +00:00
}
// Skip along to the first option delimiter "/" or "-"
2005-04-06 23:12:27 +00:00
while ( * pstrCommandLine ! = _T ( ' \0 ' ) & & * pstrCommandLine ! = _T ( ' / ' ) & & * pstrCommandLine ! = _T ( ' - ' ) ) {
2004-01-17 21:34:54 +00:00
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
}
2003-01-24 01:43:16 +00:00
2004-01-17 21:34:54 +00:00
// If there wasn't one, then must be config mode
2005-04-06 23:12:27 +00:00
if ( * pstrCommandLine = = _T ( ' \0 ' ) ) {
2004-01-17 21:34:54 +00:00
return sm_config ;
2005-04-06 23:12:27 +00:00
}
2004-01-17 21:34:54 +00:00
// Otherwise see what the option was
2005-04-06 23:12:27 +00:00
switch ( * ( + + pstrCommandLine ) ) {
2004-01-17 21:34:54 +00:00
case ' c ' :
case ' C ' :
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
while ( * pstrCommandLine & & ! isdigit ( * pstrCommandLine ) ) {
2004-01-17 21:34:54 +00:00
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
}
if ( isdigit ( * pstrCommandLine ) ) {
2004-01-17 21:34:54 +00:00
# ifdef _WIN64
2007-08-14 17:23:30 +00:00
m_hWndParent = ( HWND ) _atoi64 ( pstrCommandLine ) ;
2004-01-17 21:34:54 +00:00
# else
2007-08-14 17:23:30 +00:00
m_hWndParent = ( HWND ) _ttol ( pstrCommandLine ) ;
2003-10-22 18:39:22 +00:00
# endif
2005-04-06 23:12:27 +00:00
} else {
2004-01-17 21:34:54 +00:00
m_hWndParent = NULL ;
}
return sm_config ;
case ' t ' :
case ' T ' :
return sm_test ;
case ' p ' :
case ' P ' :
// Preview-mode, so option is followed by the parent HWND in decimal
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
while ( * pstrCommandLine & & ! isdigit ( * pstrCommandLine ) ) {
2004-01-17 21:34:54 +00:00
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
}
if ( isdigit ( * pstrCommandLine ) ) {
2004-01-17 21:34:54 +00:00
# ifdef _WIN64
2007-08-14 17:23:30 +00:00
m_hWndParent = ( HWND ) _atoi64 ( pstrCommandLine ) ;
2004-01-17 21:34:54 +00:00
# else
2007-08-14 17:23:30 +00:00
m_hWndParent = ( HWND ) _ttol ( pstrCommandLine ) ;
2003-10-22 18:39:22 +00:00
# endif
2004-01-17 21:34:54 +00:00
}
return sm_preview ;
case ' a ' :
case ' A ' :
// Password change mode, so option is followed by parent HWND in decimal
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
while ( * pstrCommandLine & & ! isdigit ( * pstrCommandLine ) ) {
2004-01-17 21:34:54 +00:00
pstrCommandLine + + ;
2005-04-06 23:12:27 +00:00
}
if ( isdigit ( * pstrCommandLine ) ) {
2004-01-17 21:34:54 +00:00
# ifdef _WIN64
2007-08-14 17:23:30 +00:00
m_hWndParent = ( HWND ) _atoi64 ( pstrCommandLine ) ;
2004-01-17 21:34:54 +00:00
# else
2007-08-14 17:23:30 +00:00
m_hWndParent = ( HWND ) _ttol ( pstrCommandLine ) ;
2003-10-22 18:39:22 +00:00
# endif
2004-01-17 21:34:54 +00:00
}
return sm_passwordchange ;
default :
// All other options => run the screensaver (typically this is "/s")
return sm_full ;
}
}
2005-04-06 23:12:27 +00:00
// Determine HMONITOR, desktop rect, and other info for each monitor.
2004-01-17 21:34:54 +00:00
// Note that EnumDisplayDevices enumerates monitors in the order
// indicated on the Settings page of the Display control panel, which
// is the order we want to list monitors in, as opposed to the order
// used by D3D's GetAdapterInfo.
2005-04-06 23:12:27 +00:00
//
VOID CScreensaver : : EnumMonitors ( VOID ) {
2004-01-17 21:34:54 +00:00
DWORD iDevice = 0 ;
DISPLAY_DEVICE_FULL dispdev ;
DISPLAY_DEVICE_FULL dispdev2 ;
DEVMODE devmode ;
dispdev . cb = sizeof ( dispdev ) ;
dispdev2 . cb = sizeof ( dispdev2 ) ;
devmode . dmSize = sizeof ( devmode ) ;
devmode . dmDriverExtra = 0 ;
INTERNALMONITORINFO * pMonitorInfoNew ;
2005-04-06 23:12:27 +00:00
while ( EnumDisplayDevices ( NULL , iDevice , ( DISPLAY_DEVICE * ) & dispdev , 0 ) ) {
2004-01-17 21:34:54 +00:00
// Ignore NetMeeting's mirrored displays
2005-04-06 23:12:27 +00:00
if ( ( dispdev . StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER ) = = 0 ) {
2004-01-17 21:34:54 +00:00
// To get monitor info for a display device, call EnumDisplayDevices
// a second time, passing dispdev.DeviceName (from the first call) as
// the first parameter.
EnumDisplayDevices ( dispdev . DeviceName , 0 , ( DISPLAY_DEVICE * ) & dispdev2 , 0 ) ;
pMonitorInfoNew = & m_Monitors [ m_dwNumMonitors ] ;
2005-04-06 23:12:27 +00:00
ZeroMemory ( pMonitorInfoNew , sizeof ( INTERNALMONITORINFO ) ) ;
StringCchCopy ( pMonitorInfoNew - > strDeviceName , 128 , dispdev . DeviceString ) ;
StringCchCopy ( pMonitorInfoNew - > strMonitorName , 128 , dispdev2 . DeviceString ) ;
2004-01-17 21:34:54 +00:00
2005-04-06 23:12:27 +00:00
if ( dispdev . StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP ) {
EnumDisplaySettings ( dispdev . DeviceName , ENUM_CURRENT_SETTINGS , & devmode ) ;
if ( dispdev . StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE ) {
2004-01-17 21:34:54 +00:00
// For some reason devmode.dmPosition is not always (0, 0)
// for the primary display, so force it.
pMonitorInfoNew - > rcScreen . left = 0 ;
pMonitorInfoNew - > rcScreen . top = 0 ;
2005-04-06 23:12:27 +00:00
} else {
2004-01-17 21:34:54 +00:00
pMonitorInfoNew - > rcScreen . left = devmode . dmPosition . x ;
pMonitorInfoNew - > rcScreen . top = devmode . dmPosition . y ;
}
pMonitorInfoNew - > rcScreen . right = pMonitorInfoNew - > rcScreen . left + devmode . dmPelsWidth ;
pMonitorInfoNew - > rcScreen . bottom = pMonitorInfoNew - > rcScreen . top + devmode . dmPelsHeight ;
2005-04-06 23:12:27 +00:00
pMonitorInfoNew - > hMonitor = MonitorFromRect ( & pMonitorInfoNew - > rcScreen , MONITOR_DEFAULTTONULL ) ;
2004-01-17 21:34:54 +00:00
}
m_dwNumMonitors + + ;
2005-04-06 23:12:27 +00:00
if ( m_dwNumMonitors = = MAX_DISPLAYS ) {
2004-01-17 21:34:54 +00:00
break ;
2005-04-06 23:12:27 +00:00
}
2003-10-22 18:39:22 +00:00
}
2004-01-17 21:34:54 +00:00
iDevice + + ;
2003-10-22 18:39:22 +00:00
}
2002-12-16 22:34:50 +00:00
}
2002-11-18 21:20:54 +00:00
2004-01-17 21:34:54 +00:00
2005-04-05 10:23:15 +00:00
// arguments: name: name of key, keyval: where to store value of key
// returns: int indicating error
// function: reads string value in specified key
2005-04-06 23:12:27 +00:00
//
int CScreensaver : : UtilSetRegKey ( LPCTSTR name , DWORD value ) {
2005-04-05 10:23:15 +00:00
LONG error ;
HKEY boinc_key ;
2004-01-17 21:34:54 +00:00
2005-04-06 23:12:27 +00:00
if ( m_bIs9x ) {
error = RegCreateKeyEx (
2005-04-05 10:23:15 +00:00
HKEY_LOCAL_MACHINE ,
_T ( " SOFTWARE \\ Space Sciences Laboratory, U.C. Berkeley \\ BOINC Screensaver " ) ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& boinc_key ,
NULL
) ;
2005-04-06 23:12:27 +00:00
if ( error ! = ERROR_SUCCESS ) return - 1 ;
2005-04-05 10:23:15 +00:00
} else {
2005-04-06 23:12:27 +00:00
error = RegCreateKeyEx (
2005-04-05 10:23:15 +00:00
HKEY_CURRENT_USER ,
_T ( " SOFTWARE \\ Space Sciences Laboratory, U.C. Berkeley \\ BOINC Screensaver " ) ,
0 ,
NULL ,
REG_OPTION_NON_VOLATILE ,
KEY_READ | KEY_WRITE ,
NULL ,
& boinc_key ,
NULL
) ;
2005-04-06 23:12:27 +00:00
if ( error ! = ERROR_SUCCESS ) return - 1 ;
2005-04-05 10:23:15 +00:00
}
2004-01-17 21:34:54 +00:00
2005-04-06 23:12:27 +00:00
error = RegSetValueEx ( boinc_key , name , 0 , REG_DWORD , ( CONST BYTE * ) & value , 4 ) ;
2004-11-14 08:29:32 +00:00
2005-04-06 23:12:27 +00:00
RegCloseKey ( boinc_key ) ;
2004-01-17 21:34:54 +00:00
2005-04-05 10:23:15 +00:00
return 0 ;
2002-12-16 22:34:50 +00:00
}
2004-01-17 21:34:54 +00:00
2005-04-05 10:23:15 +00:00
// arguments: name: name of key, keyval: where to store value of key
// returns: int indicating error
// function: reads string value in specified key
2005-04-06 23:12:27 +00:00
//
int CScreensaver : : UtilGetRegKey ( LPCTSTR name , DWORD & keyval ) {
2005-04-05 10:23:15 +00:00
LONG error ;
DWORD type = REG_DWORD ;
2005-04-06 23:12:27 +00:00
DWORD size = sizeof ( DWORD ) ;
2005-04-05 10:23:15 +00:00
DWORD value ;
HKEY boinc_key ;
2005-04-06 23:12:27 +00:00
if ( m_bIs9x ) {
error = RegOpenKeyEx (
2005-04-05 10:23:15 +00:00
HKEY_LOCAL_MACHINE ,
_T ( " SOFTWARE \\ Space Sciences Laboratory, U.C. Berkeley \\ BOINC Screensaver " ) ,
0 ,
KEY_ALL_ACCESS ,
& boinc_key
) ;
2005-04-06 23:12:27 +00:00
if ( error ! = ERROR_SUCCESS ) return - 1 ;
2005-04-05 10:23:15 +00:00
} else {
error = RegOpenKeyEx (
HKEY_CURRENT_USER ,
_T ( " SOFTWARE \\ Space Sciences Laboratory, U.C. Berkeley \\ BOINC Screensaver " ) ,
0 ,
KEY_ALL_ACCESS ,
& boinc_key
) ;
2005-04-06 23:12:27 +00:00
if ( error ! = ERROR_SUCCESS ) return - 1 ;
2005-04-05 10:23:15 +00:00
}
2005-04-06 23:12:27 +00:00
error = RegQueryValueEx ( boinc_key , name , NULL , & type , ( BYTE * ) & value , & size ) ;
2005-04-05 10:23:15 +00:00
keyval = value ;
2005-04-06 23:12:27 +00:00
RegCloseKey ( boinc_key ) ;
2005-04-05 10:23:15 +00:00
2005-04-06 23:12:27 +00:00
if ( error ! = ERROR_SUCCESS ) return - 1 ;
2005-04-05 10:23:15 +00:00
return 0 ;
}
// arguments: name: name of key, str: value of string to store
// if str is empty, attepts to delete the key
// returns: int indicating error
// function: sets string value in specified key in windows startup dir
2005-04-06 23:12:27 +00:00
//
int CScreensaver : : UtilGetRegStartupStr ( LPCTSTR name , LPTSTR str ) {
2005-04-05 10:23:15 +00:00
LONG error ;
DWORD type = REG_SZ ;
DWORD size = 128 ;
HKEY boinc_key ;
* str = 0 ;
2005-04-06 23:12:27 +00:00
if ( m_bIs9x ) {
error = RegOpenKeyEx (
2005-04-05 10:23:15 +00:00
HKEY_LOCAL_MACHINE ,
_T ( " Software \\ Microsoft \\ Windows \\ CurrentVersion \\ Run " ) ,
0 ,
KEY_ALL_ACCESS ,
& boinc_key
) ;
2005-04-06 23:12:27 +00:00
if ( error ! = ERROR_SUCCESS ) return - 1 ;
2005-04-05 10:23:15 +00:00
} else {
2005-04-06 23:12:27 +00:00
error = RegOpenKeyEx (
2005-04-05 10:23:15 +00:00
HKEY_CURRENT_USER ,
_T ( " Software \\ Microsoft \\ Windows \\ CurrentVersion \\ Run " ) ,
0 ,
KEY_ALL_ACCESS ,
& boinc_key
) ;
2005-04-06 23:12:27 +00:00
if ( error ! = ERROR_SUCCESS ) return - 1 ;
2005-04-05 10:23:15 +00:00
}
2005-04-06 23:12:27 +00:00
error = RegQueryValueEx ( boinc_key , name , NULL , & type , ( BYTE * ) str , & size ) ;
2005-04-05 10:23:15 +00:00
2005-04-06 23:12:27 +00:00
RegCloseKey ( boinc_key ) ;
2005-04-05 10:23:15 +00:00
2005-04-06 23:12:27 +00:00
if ( error ! = ERROR_SUCCESS ) return - 1 ;
2005-04-05 10:23:15 +00:00
return ERROR_SUCCESS ;
}
2005-04-06 23:12:27 +00:00
// Determine if BOINC is configured to automatically start at logon/startup.
//
BOOL CScreensaver : : IsConfigStartupBOINC ( ) {
2005-04-05 10:23:15 +00:00
BOOL bRetVal ;
BOOL bCheckFileExists ;
TCHAR szBuffer [ MAX_PATH ] ;
2006-01-27 08:55:22 +00:00
TCHAR szShortcutBuffer [ MAX_PATH ] ;
2005-04-05 10:23:15 +00:00
HANDLE hFileHandle ;
HMODULE hShell32 ;
MYSHGETFOLDERPATH pfnMySHGetFolderPath = NULL ;
// Lets set the default value to FALSE
bRetVal = FALSE ;
2006-01-27 08:55:22 +00:00
// Load the shortcut filename into the shortcut buffer.
LoadString ( NULL , IDS_SHORTCUTNAME , szShortcutBuffer , sizeof ( szShortcutBuffer ) / sizeof ( TCHAR ) ) ;
2005-04-05 10:23:15 +00:00
// Attempt to link to dynamic function if it exists
hShell32 = LoadLibrary ( _T ( " SHELL32.DLL " ) ) ;
2005-04-06 23:12:27 +00:00
if ( NULL ! = hShell32 )
2005-04-05 10:23:15 +00:00
pfnMySHGetFolderPath = ( MYSHGETFOLDERPATH ) GetProcAddress ( hShell32 , _T ( " SHGetFolderPathA " ) ) ;
// Now lets begin looking in the registry
2005-04-06 23:12:27 +00:00
if ( ERROR_SUCCESS = = UtilGetRegStartupStr ( REG_STARTUP_NAME , szBuffer ) ) {
2005-04-05 10:23:15 +00:00
bRetVal = TRUE ;
2005-04-06 23:12:27 +00:00
} else {
2005-04-05 10:23:15 +00:00
// It could be in the global startup group
2005-04-06 23:12:27 +00:00
ZeroMemory ( szBuffer , sizeof ( szBuffer ) ) ;
2005-04-05 10:23:15 +00:00
bCheckFileExists = FALSE ;
2005-04-06 23:12:27 +00:00
if ( NULL ! = pfnMySHGetFolderPath ) {
if ( SUCCEEDED ( ( pfnMySHGetFolderPath ) ( NULL , CSIDL_STARTUP | CSIDL_FLAG_CREATE , NULL , SHGFP_TYPE_CURRENT , szBuffer ) ) ) {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: pfnMySHGetFolderPath - CSIDL_STARTUP - '%s' \n " ) , szBuffer ) ;
2006-01-27 08:55:22 +00:00
StringCchCatN ( szBuffer , sizeof ( szBuffer ) , _T ( " \\ " ) , sizeof ( _T ( " \\ " ) ) / sizeof ( TCHAR ) ) ;
if ( SUCCEEDED ( StringCchCatN ( szBuffer , sizeof ( szBuffer ) , szShortcutBuffer , sizeof ( szShortcutBuffer ) / sizeof ( TCHAR ) ) ) ) {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: Final pfnMySHGetFolderPath - CSIDL_STARTUP - '%s' \n " ) , szBuffer ) ;
bCheckFileExists = TRUE ;
2005-04-06 23:12:27 +00:00
} else {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: FAILED pfnMySHGetFolderPath - CSIDL_STARTUP Append Operation \n " ) ) ;
}
2005-04-06 23:12:27 +00:00
} else {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: FAILED pfnMySHGetFolderPath - CSIDL_STARTUP \n " ) ) ;
}
}
2005-04-06 23:12:27 +00:00
if ( bCheckFileExists ) {
2005-04-05 10:23:15 +00:00
hFileHandle = CreateFile (
szBuffer ,
GENERIC_READ ,
FILE_SHARE_READ ,
NULL ,
OPEN_EXISTING ,
FILE_ATTRIBUTE_NORMAL ,
NULL ) ;
2005-04-06 23:12:27 +00:00
if ( INVALID_HANDLE_VALUE ! = hFileHandle ) {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: CreateFile returned a valid handle '%d' \n " ) , hFileHandle ) ;
CloseHandle ( hFileHandle ) ;
bRetVal = TRUE ;
2005-04-06 23:12:27 +00:00
} else {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: CreateFile returned INVALID_HANDLE_VALUE - GetLastError() '%d' \n " ) , GetLastError ( ) ) ;
// It could be in the global startup group
2005-04-06 23:12:27 +00:00
ZeroMemory ( szBuffer , sizeof ( szBuffer ) ) ;
2005-04-05 10:23:15 +00:00
bCheckFileExists = FALSE ;
2005-04-06 23:12:27 +00:00
if ( NULL ! = pfnMySHGetFolderPath ) {
if ( SUCCEEDED ( ( pfnMySHGetFolderPath ) ( NULL , CSIDL_COMMON_STARTUP | CSIDL_FLAG_CREATE , NULL , SHGFP_TYPE_CURRENT , szBuffer ) ) ) {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: pfnMySHGetFolderPath - CSIDL_COMMON_STARTUP - '%s' \n " ) , szBuffer ) ;
2006-01-27 08:55:22 +00:00
StringCchCatN ( szBuffer , sizeof ( szBuffer ) , _T ( " \\ " ) , sizeof ( _T ( " \\ " ) ) / sizeof ( TCHAR ) ) ;
if ( SUCCEEDED ( StringCchCatN ( szBuffer , sizeof ( szBuffer ) , szShortcutBuffer , sizeof ( szShortcutBuffer ) / sizeof ( TCHAR ) ) ) ) {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: Final pfnMySHGetFolderPath - CSIDL_COMMON_STARTUP - '%s' \n " ) , szBuffer ) ;
bCheckFileExists = TRUE ;
2005-04-06 23:12:27 +00:00
} else {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: FAILED pfnMySHGetFolderPath - CSIDL_COMMON_STARTUP Append Operation \n " ) ) ;
}
2005-04-06 23:12:27 +00:00
} else {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: FAILED pfnMySHGetFolderPath - CSIDL_COMMON_STARTUP \n " ) ) ;
}
}
2005-04-06 23:12:27 +00:00
if ( bCheckFileExists ) {
2005-04-05 10:23:15 +00:00
hFileHandle = CreateFile (
szBuffer ,
GENERIC_READ ,
FILE_SHARE_READ ,
NULL ,
OPEN_EXISTING ,
FILE_ATTRIBUTE_NORMAL ,
NULL ) ;
2005-04-06 23:12:27 +00:00
if ( INVALID_HANDLE_VALUE ! = hFileHandle ) {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: CreateFile returned a valid handle '%d' \n " ) , hFileHandle ) ;
CloseHandle ( hFileHandle ) ;
bRetVal = TRUE ;
2005-04-06 23:12:27 +00:00
} else {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: CreateFile returned INVALID_HANDLE_VALUE - GetLastError() '%d' \n " ) , GetLastError ( ) ) ;
}
}
}
}
}
// Free the dynamically linked to library
FreeLibrary ( hShell32 ) ;
BOINCTRACE ( _T ( " CScreensaver::IsConfigStartupBOINC: Returning '%d' \n " ) , bRetVal ) ;
return bRetVal ;
}
2006-04-13 00:28:31 +00:00
2005-04-05 10:23:15 +00:00
// Desc: Create the infrastructure for thread safe acccess to the infrastructure
// layer of the screen saver.
2005-04-06 23:12:27 +00:00
//
BOOL CScreensaver : : CreateInfrastructureMutexes ( ) {
m_hErrorManagementMutex = CreateMutex ( NULL , FALSE , NULL ) ;
if ( NULL = = m_hErrorManagementMutex ) {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::CreateInfrastructureMutexes: Failed to create m_hErrorManagementMutex '%d' \n " ) , GetLastError ( ) ) ;
return FALSE ;
}
return TRUE ;
}
2006-04-13 00:28:31 +00:00
2005-04-06 23:12:27 +00:00
// Provide a thread-safe implementation for retrieving the current
2005-04-05 10:23:15 +00:00
// error condition.
2005-04-06 23:12:27 +00:00
//
BOOL CScreensaver : : GetError (
BOOL & bErrorMode , HRESULT & hrError , TCHAR * pszError , size_t iErrorSize
) {
2005-04-05 10:23:15 +00:00
DWORD dwWaitResult ;
BOOL bRetVal = FALSE ;
// Request ownership of mutex.
2005-04-06 23:12:27 +00:00
dwWaitResult = WaitForSingleObject (
2005-04-05 10:23:15 +00:00
m_hErrorManagementMutex , // handle to mutex
5000L ) ; // five-second time-out interval
2005-04-06 23:12:27 +00:00
switch ( dwWaitResult ) {
2005-04-05 10:23:15 +00:00
// WAIT_OBJECT_0 - The thread got mutex ownership.
case WAIT_OBJECT_0 :
bErrorMode = m_bErrorMode ;
hrError = m_hrError ;
2005-04-06 23:12:27 +00:00
if ( NULL ! = pszError ) {
2005-04-05 10:23:15 +00:00
StringCbCopyN ( pszError , iErrorSize , m_szError , sizeof ( m_szError ) * sizeof ( TCHAR ) ) ;
2005-04-06 23:12:27 +00:00
}
2005-04-05 10:23:15 +00:00
bRetVal = TRUE ;
break ;
// WAIT_TIMEOUT - Cannot get mutex ownership due to time-out.
// WAIT_ABANDONED - Got ownership of the abandoned mutex object.
case WAIT_TIMEOUT :
case WAIT_ABANDONED :
break ;
}
2005-04-06 23:12:27 +00:00
ReleaseMutex ( m_hErrorManagementMutex ) ;
2005-04-05 10:23:15 +00:00
return bRetVal ;
}
2005-04-06 23:12:27 +00:00
// Provide a thread-safe implementation for setting the current
2005-04-05 10:23:15 +00:00
// error condition. This API should only be called in the data management
// thread, any other thread may cause a race condition.
2005-04-06 23:12:27 +00:00
//
BOOL CScreensaver : : SetError ( BOOL bErrorMode , HRESULT hrError ) {
2005-04-05 10:23:15 +00:00
DWORD dwWaitResult ;
BOOL bRetVal = FALSE ;
// Request ownership of mutex.
2005-04-06 23:12:27 +00:00
dwWaitResult = WaitForSingleObject (
2005-04-05 10:23:15 +00:00
m_hErrorManagementMutex , // handle to mutex
2005-04-06 23:12:27 +00:00
5000L // five-second time-out interval
) ;
2005-04-05 10:23:15 +00:00
2005-04-06 23:12:27 +00:00
switch ( dwWaitResult ) {
2005-04-05 10:23:15 +00:00
// WAIT_OBJECT_0 - The thread got mutex ownership.
case WAIT_OBJECT_0 :
m_bErrorMode = bErrorMode ;
m_hrError = hrError ;
// Update the error text, including a possible RPC call
// to the daemon.
UpdateErrorBoxText ( ) ;
bRetVal = TRUE ;
break ;
// WAIT_TIMEOUT - Cannot get mutex ownership due to time-out.
// WAIT_ABANDONED - Got ownership of the abandoned mutex object.
case WAIT_TIMEOUT :
case WAIT_ABANDONED :
break ;
}
2005-04-06 23:12:27 +00:00
ReleaseMutex ( m_hErrorManagementMutex ) ;
2005-04-05 10:23:15 +00:00
return bRetVal ;
}
2006-04-13 00:28:31 +00:00
2005-04-06 23:12:27 +00:00
// Update the error message
//
VOID CScreensaver : : UpdateErrorBoxText ( ) {
2005-04-05 10:23:15 +00:00
PROJECT * pProject ;
2007-10-02 21:44:14 +00:00
bool bIsActive = false ;
bool bIsExecuting = false ;
bool bIsDownloaded = false ;
2007-08-14 17:23:30 +00:00
size_t iResultCount = 0 ;
size_t iIndex = 0 ;
2005-04-05 10:23:15 +00:00
2008-01-30 04:22:42 +00:00
if ( ( SCRAPPERR_BOINCNOGRAPHICSAPPSEXECUTING = = m_hrError )
| | ( SCRAPPERR_DAEMONALLOWSNOGRAPHICS = = m_hrError )
) {
2007-10-05 13:28:11 +00:00
if ( m_updating_results ) return ; // results vector is currently being updated by rpc
2007-08-15 15:25:52 +00:00
iResultCount = results . results . size ( ) ;
2007-10-02 21:44:14 +00:00
int iModIndex ;
2007-08-15 15:25:52 +00:00
for ( iIndex = 0 ; iIndex < iResultCount ; iIndex + + ) {
2007-10-02 21:44:14 +00:00
// cycle through the active results starting from the last one
iModIndex = ( iIndex + m_iLastResultShown + 1 ) % iResultCount ;
bIsDownloaded = ( RESULT_FILES_DOWNLOADED = = results . results . at ( iModIndex ) - > state ) ;
bIsActive = ( results . results . at ( iModIndex ) - > active_task ) ;
bIsExecuting = ( CPU_SCHED_SCHEDULED = = results . results . at ( iModIndex ) - > scheduler_state ) ;
if ( ! ( bIsActive ) | | ! ( bIsDownloaded ) | | ! ( bIsExecuting ) ) continue ;
2008-02-19 13:27:11 +00:00
pProject = state . lookup_project ( results . results . at ( iModIndex ) - > project_url ) ;
2007-08-15 15:25:52 +00:00
if ( NULL ! = pProject ) {
2007-10-02 21:44:14 +00:00
RESULT * pResult = state . lookup_result ( pProject , results . results . at ( iModIndex ) - > name ) ;
if ( pResult ! = NULL ) {
BOINCTRACE ( _T ( " CScreensaver::UpdateErrorBoxText - Display result. iIndex=%d, iModIndex=%d, lastResult=%d \n " ) , iIndex , iModIndex , m_iLastResultShown ) ;
StringCbPrintf ( m_szError , sizeof ( m_szError ) / sizeof ( TCHAR ) ,
2008-01-29 20:04:38 +00:00
_T ( " \n Computing for %s \n Application: %s \n Task: %s \n %.2f%% complete \n " ) ,
2007-10-02 21:44:14 +00:00
pProject - > project_name . c_str ( ) ,
pResult - > app - > user_friendly_name . c_str ( ) ,
pResult - > wu_name . c_str ( ) ,
results . results . at ( iModIndex ) - > fraction_done * 100
) ;
if ( m_tLastResultChangeTime + 10 < time ( 0 ) ) {
m_iLastResultShown = iModIndex ;
m_tLastResultChangeTime = time ( 0 ) ;
}
break ;
} else {
m_bResetCoreState = TRUE ;
GetTextForError ( IDS_ERR_GENERIC , m_szError , sizeof ( m_szError ) / sizeof ( TCHAR ) ) ;
}
2007-08-15 15:25:52 +00:00
} else {
m_bResetCoreState = TRUE ;
2007-10-02 21:44:14 +00:00
GetTextForError ( IDS_ERR_GENERIC , m_szError , sizeof ( m_szError ) / sizeof ( TCHAR ) ) ;
2005-04-05 10:23:15 +00:00
}
}
2007-08-15 15:25:52 +00:00
m_szError [ sizeof ( m_szError ) - 1 ] = ' \0 ' ;
2007-10-05 13:28:11 +00:00
} else {
// Load error string
GetTextForError ( m_hrError , m_szError , sizeof ( m_szError ) / sizeof ( TCHAR ) ) ;
2005-04-05 10:23:15 +00:00
}
BOINCTRACE ( _T ( " CScreensaver::UpdateErrorBoxText - Updated Text '%s' \n " ) , m_szError ) ;
}
2006-04-13 00:28:31 +00:00
2005-04-06 23:12:27 +00:00
// Translate an HRESULT error code into a string that can be displayed
2005-04-05 10:23:15 +00:00
// to explain the error. A class derived from CD3DScreensaver can
// provide its own version of this function that provides app-specific
// error translation instead of or in addition to calling this function.
// This function returns TRUE if a specific error was translated, or
// FALSE if no specific translation for the HRESULT was found (though
// it still puts a generic string into pszError).
2005-04-06 23:12:27 +00:00
//
BOOL CScreensaver : : GetTextForError (
HRESULT hr , TCHAR * pszError , DWORD dwNumChars
) {
const DWORD dwErrorMap [ ] [ 2 ] = {
2005-04-05 10:23:15 +00:00
// HRESULT, stringID
E_FAIL , IDS_ERR_GENERIC ,
E_OUTOFMEMORY , IDS_ERR_OUTOFMEMORY ,
SCRAPPERR_BOINCNOTDETECTED , IDS_ERR_BOINCNOTDETECTED ,
SCRAPPERR_BOINCNOTDETECTEDSTARTUP , IDS_ERR_BOINCNOTDETECTEDSTARTUP ,
SCRAPPERR_BOINCSUSPENDED , IDS_ERR_BOINCSUSPENDED ,
SCRAPPERR_BOINCNOAPPSEXECUTING , IDS_ERR_BOINCNOAPPSEXECUTING ,
SCRAPPERR_BOINCNOPROJECTSDETECTED , IDS_ERR_BOINCNOAPPSEXECUTINGNOPROJECTSDETECTED ,
SCRAPPERR_BOINCNOGRAPHICSAPPSEXECUTING , IDS_ERR_BOINCNOGRAPHICSAPPSEXECUTING ,
SCRAPPERR_BOINCSCREENSAVERLOADING , IDS_ERR_BOINCSCREENSAVERLOADING ,
2006-04-12 02:28:50 +00:00
SCRAPPERR_BOINCAPPFOUNDGRAPHICSLOADING , IDS_ERR_BOINCAPPFOUNDGRAPHICSLOADING ,
2006-04-12 04:27:22 +00:00
SCRAPPERR_BOINCSHUTDOWNEVENT , IDS_ERR_BOINCSHUTDOWNEVENT ,
2006-08-28 20:28:56 +00:00
SCRAPPERR_NOPREVIEW , IDS_ERR_NOPREVIEW ,
SCRAPPERR_DAEMONALLOWSNOGRAPHICS , IDS_ERR_DAEMONALLOWSNOGRAPHICS
2005-04-05 10:23:15 +00:00
} ;
const DWORD dwErrorMapSize = sizeof ( dwErrorMap ) / sizeof ( DWORD [ 2 ] ) ;
DWORD iError ;
DWORD resid = 0 ;
2005-12-23 04:51:52 +00:00
for ( iError = 0 ; iError < dwErrorMapSize ; iError + + ) {
if ( hr = = ( HRESULT ) dwErrorMap [ iError ] [ 0 ] ) {
resid = dwErrorMap [ iError ] [ 1 ] ;
2005-04-05 10:23:15 +00:00
}
}
2005-04-06 23:12:27 +00:00
if ( resid = = 0 ) {
2005-04-05 10:23:15 +00:00
resid = IDS_ERR_GENERIC ;
}
2005-04-06 23:12:27 +00:00
LoadString ( NULL , resid , pszError , dwNumChars ) ;
2005-04-05 10:23:15 +00:00
2005-04-06 23:12:27 +00:00
if ( resid = = IDS_ERR_GENERIC ) {
2005-04-05 10:23:15 +00:00
return FALSE ;
2005-04-06 23:12:27 +00:00
} else {
2005-04-05 10:23:15 +00:00
return TRUE ;
2005-04-06 23:12:27 +00:00
}
2005-04-05 10:23:15 +00:00
}
2005-04-06 23:12:27 +00:00
// Create the thread that is used to talk to the daemon.
//
BOOL CScreensaver : : CreateDataManagementThread ( ) {
2005-05-05 06:07:14 +00:00
DWORD dwThreadID = 0 ;
2007-10-05 13:28:11 +00:00
BOINCTRACE ( _T ( " CScreensaver::CreateDataManagementThread Start \n " ) ) ;
m_QuitDataManagementProc = FALSE ;
2005-04-06 23:12:27 +00:00
m_hDataManagementThread = CreateThread (
2005-04-05 10:23:15 +00:00
NULL , // default security attributes
0 , // use default stack size
DataManagementProcStub , // thread function
NULL , // argument to thread function
0 , // use default creation flags
2005-05-05 06:07:14 +00:00
& dwThreadID ) ; // returns the thread identifier
2005-04-05 10:23:15 +00:00
2005-04-06 23:12:27 +00:00
if ( m_hDataManagementThread = = NULL ) {
2005-04-05 10:23:15 +00:00
BOINCTRACE ( _T ( " CScreensaver::CreateDataManagementThread: Failed to create data management thread '%d' \n " ) , GetLastError ( ) ) ;
return FALSE ;
}
return TRUE ;
}
2005-04-06 23:12:27 +00:00
// Terminate the thread that is used to talk to the daemon.
//
2007-10-09 10:01:27 +00:00
BOOL CScreensaver : : DestroyDataManagementThread ( ) {
2007-10-05 13:28:11 +00:00
m_QuitDataManagementProc = TRUE ; // Tell RPC Thread to exit
// Wait up to 5 seconds for DataManagementThread to exit
2007-10-09 12:18:40 +00:00
for ( int i = 0 ; i < 50 ; i + + ) {
2007-10-05 13:28:11 +00:00
DWORD dwStatus = STILL_ACTIVE ;
BOOL bRetVal = FALSE ;
2007-10-09 12:18:40 +00:00
2007-10-09 12:41:38 +00:00
boinc_sleep ( 0.1 ) ;
2007-10-05 13:28:11 +00:00
bRetVal = GetExitCodeThread ( m_hDataManagementThread , & dwStatus ) ;
2007-10-09 10:01:27 +00:00
BOINCTRACE ( _T ( " CScreensaver::DestroyDataManagementThread - GetExitCodeThread RetVal = '%d', Status = '%d' \n " ) , bRetVal , dwStatus ) ;
2007-10-05 13:28:11 +00:00
if ( bRetVal & & ( dwStatus ! = STILL_ACTIVE ) ) {
break ;
}
2005-04-05 10:23:15 +00:00
}
return TRUE ;
}
2006-04-13 00:28:31 +00:00
2007-10-05 13:28:11 +00:00
// This function forwards to DataManagementProc, which has access to the
// "this" pointer.
2005-04-06 23:12:27 +00:00
//
2007-10-05 13:28:11 +00:00
DWORD WINAPI CScreensaver : : DataManagementProcStub ( LPVOID UNUSED ( lpParam ) ) {
return gspScreensaver - > DataManagementProc ( ) ;
}
2005-04-05 10:23:15 +00:00
2007-10-02 21:44:14 +00:00
2007-10-05 13:28:11 +00:00
void CScreensaver : : HandleRPCError ( )
{
// Attempt to reinitialize the RPC client and state
rpc - > close ( ) ;
rpc - > init ( NULL ) ;
m_bResetCoreState = TRUE ;
2005-04-05 20:02:59 +00:00
2007-10-05 13:28:11 +00:00
if ( ! m_bBOINCConfigChecked ) {
m_bBOINCConfigChecked = TRUE ;
m_bBOINCStartupConfigured = IsConfigStartupBOINC ( ) ;
}
2005-04-05 10:23:15 +00:00
2007-10-05 13:28:11 +00:00
if ( ( time ( 0 ) - m_tThreadCreateTime ) > 3 ) {
if ( m_bBOINCStartupConfigured ) {
SetError ( TRUE , SCRAPPERR_BOINCNOTDETECTED ) ;
} else {
SetError ( TRUE , SCRAPPERR_BOINCNOTDETECTEDSTARTUP ) ;
}
}
2005-04-05 20:02:59 +00:00
2007-10-05 13:28:11 +00:00
}
2005-04-05 20:02:59 +00:00
2005-04-05 10:23:15 +00:00
2007-10-05 13:28:11 +00:00
void CScreensaver : : CheckForegroundWindow ( )
{
BOOL bForegroundWindowIsScreensaver ;
HWND hwndBOINCGraphicsWindow = NULL ;
HWND hwndForeWindow = NULL ;
HWND hwndForeParent = NULL ;
DWORD iMonitor = 0 ;
INTERNALMONITORINFO * pMonitorInfo = NULL ;
2005-04-05 10:23:15 +00:00
2007-10-05 13:28:11 +00:00
// When running in screensaver mode the only two valid conditions for z-order
// is that either the screensaver or graphics application is the foreground
// application. If this is not true, then blow out of the screensaver.
hwndBOINCGraphicsWindow = FindWindow ( BOINC_WINDOW_CLASS_NAME , NULL ) ;
if ( hwndBOINCGraphicsWindow ) {
// Graphics Application.
hwndForeWindow = GetForegroundWindow ( ) ;
// If the graphics application is not the top most window try and force it
// to the top.
if ( hwndForeWindow ! = hwndBOINCGraphicsWindow ) {
BOINCTRACE ( _T ( " CScreensaver::CheckForegroundWindow - Graphics Window Detected but NOT the foreground window, bringing window to foreground. \n " ) ) ;
SetForegroundWindow ( hwndBOINCGraphicsWindow ) ;
hwndForeWindow = GetForegroundWindow ( ) ;
if ( hwndForeWindow ! = hwndBOINCGraphicsWindow ) {
BOINCTRACE ( _T ( " CScreensaver::CheckForegroundWindow - Graphics Window Detected but NOT the foreground window, bringing window to foreground. (Final Try) \n " ) ) ;
// This may be needed on Windows 2000 or better machines
if ( gspfnMyBroadcastSystemMessage ) {
DWORD dwComponents = BSM_APPLICATIONS ;
gspfnMyBroadcastSystemMessage (
BSF_ALLOWSFW ,
& dwComponents ,
WM_BOINCSFW ,
NULL ,
NULL
) ;
2005-04-06 23:12:27 +00:00
}
2005-04-05 20:02:59 +00:00
}
2005-04-06 23:12:27 +00:00
} else {
2007-10-05 13:28:11 +00:00
// Science application has focus, and is visible.
//
// Some science application take a really long time to display something on their
// window, during this time the window will appear to eat keyboard and mouse event
// messages and not respond to other system events. These windows are considered
// ghost windows, normally they have an outline and can be moved around and resized.
// In the science application case where the borders are hidden from view, the
// window just takes on the background of the previous window which happens to be
// the black screensaver window owned by this process.
//
// Verify that their hasn't been any keyboard or mouse activity. If there has
// we should hide the window from this process and exit out of the screensaver to
// return control back to the user as quickly as possible.
BOINCTRACE ( _T ( " CScreensaver::CheckForegroundWindow - Graphics Window Detected and is the foreground window. \n " ) ) ;
if ( gspfnMyGetLastInputInfo ) {
BOINCTRACE ( _T ( " CScreensaver::CheckForegroundWindow - Checking idle actvity. \n " ) ) ;
LASTINPUTINFO lii ;
lii . cbSize = sizeof ( LASTINPUTINFO ) ;
gspfnMyGetLastInputInfo ( & lii ) ;
if ( m_dwLastInputTimeAtStartup ! = lii . dwTime ) {
BOINCTRACE ( _T ( " CScreensaver::CheckForegroundWindow - Activity Detected. \n " ) ) ;
ShowWindow ( hwndBOINCGraphicsWindow , SW_MINIMIZE ) ;
ShowWindow ( hwndBOINCGraphicsWindow , SW_FORCEMINIMIZE ) ;
SetError ( TRUE , SCRAPPERR_BOINCSHUTDOWNEVENT ) ;
SendMessage ( m_Monitors [ iMonitor ] . hWnd , WM_INTERRUPTSAVER , NULL , NULL ) ;
2005-04-05 10:23:15 +00:00
}
}
}
2007-10-05 13:28:11 +00:00
} else {
// Graphics application does not exist. So check that one of the windows
// assigned to each monitor is the foreground window.
bForegroundWindowIsScreensaver = FALSE ;
hwndForeWindow = GetForegroundWindow ( ) ;
hwndForeParent = GetParent ( hwndForeWindow ) ;
for ( iMonitor = 0 ; iMonitor < m_dwNumMonitors ; iMonitor + + ) {
pMonitorInfo = & m_Monitors [ iMonitor ] ;
if ( ( pMonitorInfo - > hWnd = = hwndForeWindow ) | |
( pMonitorInfo - > hWnd = = hwndForeParent ) )
{
bForegroundWindowIsScreensaver = TRUE ;
}
}
if ( ! bForegroundWindowIsScreensaver ) {
// This can happen because of a personal firewall notifications or some
// funky IM client that thinks it has to notify the user even when in
// screensaver mode.
BOINCTRACE ( _T ( " CScreensaver::CheckForegroundWindow - Unknown foreground window detected, shutdown the screensaver. \n " ) ) ;
SetError ( TRUE , SCRAPPERR_BOINCSHUTDOWNEVENT ) ;
SendMessage ( m_Monitors [ 0 ] . hWnd , WM_INTERRUPTSAVER , NULL , NULL ) ;
}
2005-04-05 10:23:15 +00:00
}
}
2006-04-13 00:28:31 +00:00
2005-04-06 23:12:27 +00:00
// Register and create the appropriate window(s)
//
HRESULT CScreensaver : : CreateSaverWindow ( ) {
2005-04-05 10:23:15 +00:00
// Register an appropriate window class for the primary display
WNDCLASS cls ;
2005-04-06 23:12:27 +00:00
cls . hCursor = LoadCursor ( NULL , IDC_ARROW ) ;
cls . hIcon = LoadIcon ( m_hInstance , MAKEINTRESOURCE ( IDI_MAIN_ICON ) ) ;
2005-04-05 10:23:15 +00:00
cls . lpszMenuName = NULL ;
cls . lpszClassName = _T ( " BOINCPrimarySaverWndClass " ) ;
cls . hbrBackground = ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ;
cls . hInstance = m_hInstance ;
cls . style = CS_VREDRAW | CS_HREDRAW ;
cls . lpfnWndProc = SaverProcStub ;
cls . cbWndExtra = 0 ;
cls . cbClsExtra = 0 ;
2005-04-06 23:12:27 +00:00
RegisterClass ( & cls ) ;
2005-04-05 10:23:15 +00:00
// Register an appropriate window class for the secondary display(s)
WNDCLASS cls2 ;
2005-04-06 23:12:27 +00:00
cls2 . hCursor = LoadCursor ( NULL , IDC_ARROW ) ;
cls2 . hIcon = LoadIcon ( m_hInstance , MAKEINTRESOURCE ( IDI_MAIN_ICON ) ) ;
2005-04-05 10:23:15 +00:00
cls2 . lpszMenuName = NULL ;
cls2 . lpszClassName = _T ( " BOINCGenericSaverWndClass " ) ;
cls2 . hbrBackground = ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ;
cls2 . hInstance = m_hInstance ;
cls2 . style = CS_VREDRAW | CS_HREDRAW ;
cls2 . lpfnWndProc = SaverProcStub ;
cls2 . cbWndExtra = 0 ;
cls2 . cbClsExtra = 0 ;
2005-04-06 23:12:27 +00:00
RegisterClass ( & cls2 ) ;
2005-04-05 10:23:15 +00:00
// Create the window
RECT rc ;
DWORD dwStyle ;
2005-04-06 23:12:27 +00:00
switch ( m_SaverMode ) {
2005-04-05 10:23:15 +00:00
case sm_preview :
2005-04-06 23:12:27 +00:00
GetClientRect ( m_hWndParent , & rc ) ;
2005-04-05 10:23:15 +00:00
dwStyle = WS_VISIBLE | WS_CHILD ;
2005-04-06 23:12:27 +00:00
AdjustWindowRect ( & rc , dwStyle , FALSE ) ;
2006-04-13 08:37:25 +00:00
m_hWnd = CreateWindow ( _T ( " BOINCPrimarySaverWndClass " ) ,
m_strWindowTitle , dwStyle , rc . left , rc . top , rc . right - rc . left ,
rc . bottom - rc . top , m_hWndParent , NULL , m_hInstance , this
2005-04-06 23:12:27 +00:00
) ;
2005-04-05 10:23:15 +00:00
m_Monitors [ 0 ] . hWnd = m_hWnd ;
2005-04-06 23:12:27 +00:00
GetClientRect ( m_hWnd , & m_rcRenderTotal ) ;
GetClientRect ( m_hWnd , & m_rcRenderCurDevice ) ;
2005-04-05 10:23:15 +00:00
break ;
case sm_test :
rc . left = rc . top = 50 ;
rc . right = rc . left + 600 ;
rc . bottom = rc . top + 400 ;
dwStyle = WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU ;
2005-04-06 23:12:27 +00:00
AdjustWindowRect ( & rc , dwStyle , FALSE ) ;
2006-04-13 08:37:25 +00:00
m_hWnd = CreateWindow ( _T ( " BOINCPrimarySaverWndClass " ) ,
m_strWindowTitle , dwStyle , rc . left , rc . top , rc . right - rc . left ,
rc . bottom - rc . top , NULL , NULL , m_hInstance , this
2005-04-06 23:12:27 +00:00
) ;
2005-04-05 10:23:15 +00:00
m_Monitors [ 0 ] . hWnd = m_hWnd ;
2005-04-06 23:12:27 +00:00
GetClientRect ( m_hWnd , & m_rcRenderTotal ) ;
GetClientRect ( m_hWnd , & m_rcRenderCurDevice ) ;
2005-04-05 10:23:15 +00:00
SetTimer ( m_hWnd , 2 , 60000 , NULL ) ;
break ;
case sm_full :
dwStyle = WS_VISIBLE | WS_POPUP ;
m_hWnd = NULL ;
2005-04-06 23:12:27 +00:00
for ( DWORD iMonitor = 0 ; iMonitor < m_dwNumMonitors ; iMonitor + + ) {
2005-04-05 10:23:15 +00:00
INTERNALMONITORINFO * pMonitorInfo ;
pMonitorInfo = & m_Monitors [ iMonitor ] ;
2005-04-06 23:12:27 +00:00
if ( pMonitorInfo - > hWnd = = NULL ) {
if ( pMonitorInfo - > hMonitor = = NULL )
2005-04-05 10:23:15 +00:00
continue ;
rc = pMonitorInfo - > rcScreen ;
2005-04-06 23:12:27 +00:00
if ( 0 = = iMonitor ) {
2006-04-13 08:37:25 +00:00
pMonitorInfo - > hWnd = CreateWindowEx ( NULL , _T ( " BOINCPrimarySaverWndClass " ) ,
2005-04-05 10:23:15 +00:00
m_strWindowTitle , dwStyle , rc . left , rc . top , rc . right - rc . left ,
2005-04-06 23:12:27 +00:00
rc . bottom - rc . top , NULL , NULL , m_hInstance , this ) ;
} else {
2006-04-13 08:37:25 +00:00
pMonitorInfo - > hWnd = CreateWindowEx ( NULL , _T ( " BOINCGenericSaverWndClass " ) ,
2005-04-05 10:23:15 +00:00
m_strWindowTitle , dwStyle , rc . left , rc . top , rc . right - rc . left ,
2005-04-06 23:12:27 +00:00
rc . bottom - rc . top , NULL , NULL , m_hInstance , this ) ;
2005-04-05 10:23:15 +00:00
}
2005-04-06 23:12:27 +00:00
if ( pMonitorInfo - > hWnd = = NULL ) {
2005-04-05 10:23:15 +00:00
return E_FAIL ;
2005-04-06 23:12:27 +00:00
}
2005-04-05 10:23:15 +00:00
2005-04-06 23:12:27 +00:00
if ( m_hWnd = = NULL ) {
2005-04-05 10:23:15 +00:00
m_hWnd = pMonitorInfo - > hWnd ;
2005-04-06 23:12:27 +00:00
}
2005-04-05 10:23:15 +00:00
2006-07-25 10:19:27 +00:00
SetTimer ( pMonitorInfo - > hWnd , 2 , 250 , NULL ) ;
2005-04-05 10:23:15 +00:00
}
}
}
2005-04-06 23:12:27 +00:00
if ( m_hWnd = = NULL ) {
2005-04-05 10:23:15 +00:00
return E_FAIL ;
2005-04-06 23:12:27 +00:00
}
2005-04-05 10:23:15 +00:00
return S_OK ;
}
2005-04-06 23:12:27 +00:00
// Run the screensaver graphics - may be preview, test or full-on mode
//
HRESULT CScreensaver : : DoSaver ( ) {
2004-01-17 21:34:54 +00:00
// Flag as screensaver running if in full on mode
2005-04-06 23:12:27 +00:00
if ( m_SaverMode = = sm_full ) {
2004-01-17 21:34:54 +00:00
BOOL bUnused ;
2005-04-06 23:12:27 +00:00
SystemParametersInfo ( SPI_SCREENSAVERRUNNING , TRUE , & bUnused , 0 ) ;
2004-01-17 21:34:54 +00:00
}
// Message pump
BOOL bGotMsg ;
MSG msg ;
msg . message = WM_NULL ;
2005-04-06 23:12:27 +00:00
while ( msg . message ! = WM_QUIT ) {
bGotMsg = PeekMessage ( & msg , NULL , 0 , 0 , PM_REMOVE ) ;
if ( bGotMsg ) {
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
} else {
2004-01-17 21:34:54 +00:00
Sleep ( 10 ) ;
}
}
return S_OK ;
}
2005-04-06 23:12:27 +00:00
VOID CScreensaver : : DoConfig ( ) {
DialogBox ( NULL , MAKEINTRESOURCE ( DLG_CONFIG ) , m_hWndParent , ConfigureDialogProcStub ) ;
2004-01-17 21:34:54 +00:00
}
2005-04-06 23:12:27 +00:00
// Handle window messages for main screensaver windows.
//
LRESULT CScreensaver : : SaverProc (
HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam
) {
2005-03-23 00:16:58 +00:00
DWORD dwMonitor = 0 ;
# ifdef _DEBUG
2005-04-06 23:12:27 +00:00
for ( DWORD iIndex = 0 ; iIndex < m_dwNumMonitors ; iIndex + + ) {
if ( hWnd = = m_Monitors [ iIndex ] . hWnd ) {
2005-03-23 00:16:58 +00:00
dwMonitor = iIndex ;
2005-04-06 23:12:27 +00:00
}
}
2005-03-23 00:16:58 +00:00
# endif
2006-04-13 08:37:25 +00:00
BOINCTRACE ( _T ( " CScreensaver::SaverProc [%d] hWnd '%d' uMsg '%X' wParam '%d' lParam '%d' \n " ) , dwMonitor , hWnd , uMsg , wParam , lParam ) ;
2005-04-06 23:12:27 +00:00
switch ( uMsg ) {
2004-01-17 21:34:54 +00:00
case WM_TIMER :
2006-04-13 04:21:23 +00:00
BOINCTRACE ( _T ( " CScreensaver::SaverProc Received WM_TIMER \n " ) ) ;
2005-04-06 23:12:27 +00:00
switch ( wParam ) {
2004-01-17 21:34:54 +00:00
case 1 :
// Initial idle time is done, proceed with initialization.
m_bWaitForInputIdle = FALSE ;
2005-04-06 23:12:27 +00:00
KillTimer ( hWnd , 1 ) ;
2006-04-13 08:37:25 +00:00
return 0 ;
2005-02-03 01:55:34 +00:00
break ;
2004-11-17 09:27:06 +00:00
case 2 :
2005-04-05 10:23:15 +00:00
// Create a screen saver window on the primary display if
// the boinc client crashes
CreateSaverWindow ( ) ;
2005-02-03 01:55:34 +00:00
2005-04-05 10:23:15 +00:00
// Update the position of the box every second so that it
// does not end up off the visible area of the screen.
UpdateErrorBox ( ) ;
2006-04-13 08:37:25 +00:00
return 0 ;
2005-04-05 10:23:15 +00:00
break ;
2005-02-03 01:55:34 +00:00
}
2004-01-17 21:34:54 +00:00
break ;
2005-03-23 00:16:58 +00:00
case WM_PAINT :
2004-01-17 21:34:54 +00:00
{
2006-07-25 10:19:27 +00:00
BOOL bErrorMode ;
HRESULT hrError ;
TCHAR szError [ 400 ] ;
GetError ( bErrorMode , hrError , szError , sizeof ( szError ) / sizeof ( TCHAR ) ) ;
// Show error message, if there is one
2005-03-23 00:16:58 +00:00
PAINTSTRUCT ps ;
2005-04-06 23:12:27 +00:00
BeginPaint ( hWnd , & ps ) ;
2004-01-17 21:34:54 +00:00
2005-03-23 00:16:58 +00:00
// In preview mode, just fill
// the preview window with black, and the BOINC icon.
2005-04-06 23:12:27 +00:00
if ( ! bErrorMode & & m_SaverMode = = sm_preview ) {
2005-03-23 00:16:58 +00:00
RECT rc ;
GetClientRect ( hWnd , & rc ) ;
2005-04-06 23:12:27 +00:00
FillRect ( ps . hdc , & rc , ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ) ;
2005-03-23 00:16:58 +00:00
DrawIcon ( ps . hdc , ( rc . right / 2 ) - 16 , ( rc . bottom / 2 ) - 16 ,
2005-04-06 23:12:27 +00:00
LoadIcon ( m_hInstance , MAKEINTRESOURCE ( IDI_MAIN_ICON ) ) ) ;
} else {
2006-07-26 05:39:09 +00:00
DoPaint ( hWnd , ps . hdc , & ps ) ;
2005-03-23 00:16:58 +00:00
}
2004-01-17 21:34:54 +00:00
2005-04-06 23:12:27 +00:00
EndPaint ( hWnd , & ps ) ;
2004-01-17 21:34:54 +00:00
}
return 0 ;
2005-03-23 00:16:58 +00:00
break ;
2004-01-17 21:34:54 +00:00
case WM_MOUSEMOVE :
2005-04-06 23:12:27 +00:00
if ( m_SaverMode ! = sm_test ) {
2004-01-17 21:34:54 +00:00
static INT xPrev = - 1 ;
static INT yPrev = - 1 ;
INT xCur = GET_X_LPARAM ( lParam ) ;
INT yCur = GET_Y_LPARAM ( lParam ) ;
2005-04-06 23:12:27 +00:00
if ( xCur ! = xPrev | | yCur ! = yPrev ) {
2004-01-17 21:34:54 +00:00
xPrev = xCur ;
yPrev = yCur ;
m_dwSaverMouseMoveCount + + ;
2006-04-13 08:37:25 +00:00
if ( m_dwSaverMouseMoveCount > 5 ) {
BOINCTRACE ( _T ( " CScreensaver::SaverProc Received WM_MOUSEMOVE and time to InterruptSaver() \n " ) ) ;
2004-01-17 21:34:54 +00:00
InterruptSaver ( ) ;
2006-04-13 08:37:25 +00:00
}
2004-01-17 21:34:54 +00:00
}
}
2005-03-23 00:16:58 +00:00
return 0 ;
2004-01-17 21:34:54 +00:00
break ;
case WM_KEYDOWN :
case WM_LBUTTONDOWN :
case WM_RBUTTONDOWN :
case WM_MBUTTONDOWN :
2006-04-13 04:21:23 +00:00
BOINCTRACE ( _T ( " CScreensaver::SaverProc Received WM_KEYDOWN | WM_LBUTTONDOWN | WM_RBUTTONDOWN | WM_MBUTTONDOWN \n " ) ) ;
2005-04-06 23:12:27 +00:00
if ( m_SaverMode ! = sm_test ) {
2004-01-17 21:34:54 +00:00
InterruptSaver ( ) ;
2005-04-06 23:12:27 +00:00
}
2004-01-17 21:34:54 +00:00
return 0 ;
break ;
2005-03-23 00:16:58 +00:00
case WM_CLOSE :
case WM_DESTROY :
2005-04-02 18:08:55 +00:00
BOINCTRACE ( _T ( " CScreensaver::SaverProc Received WM_CLOSE or WM_DESTROY \n " ) ) ;
2005-04-06 23:12:27 +00:00
if ( m_SaverMode = = sm_preview | | m_SaverMode = = sm_test ) {
2005-03-23 00:16:58 +00:00
ShutdownSaver ( ) ;
2005-04-06 23:12:27 +00:00
}
2005-03-23 00:16:58 +00:00
return 0 ;
2004-01-17 21:34:54 +00:00
break ;
case WM_SYSCOMMAND :
2006-04-13 04:23:49 +00:00
BOINCTRACE ( _T ( " CScreensaver::SaverProc Received WM_SYSCOMMAND \n " ) ) ;
2005-04-06 23:12:27 +00:00
if ( m_SaverMode = = sm_full ) {
switch ( wParam ) {
2004-01-17 21:34:54 +00:00
case SC_NEXTWINDOW :
case SC_PREVWINDOW :
case SC_SCREENSAVE :
case SC_CLOSE :
2006-04-13 08:37:25 +00:00
return 0 ;
2005-04-06 23:12:27 +00:00
}
2004-01-17 21:34:54 +00:00
}
break ;
case WM_SETCURSOR :
2006-04-13 04:21:23 +00:00
BOINCTRACE ( _T ( " CScreensaver::SaverProc Received WM_SETCURSOR \n " ) ) ;
2005-04-06 23:12:27 +00:00
if ( m_SaverMode = = sm_full & & ! m_bCheckingSaverPassword ) {
2004-01-17 21:34:54 +00:00
// Hide cursor
2005-04-06 23:12:27 +00:00
SetCursor ( NULL ) ;
2004-01-17 21:34:54 +00:00
return TRUE ;
}
break ;
case WM_POWERBROADCAST :
2006-04-13 04:21:23 +00:00
BOINCTRACE ( _T ( " CScreensaver::SaverProc Received WM_POWERBROADCAST \n " ) ) ;
2006-04-13 00:28:31 +00:00
if ( wParam = = PBT_APMQUERYSUSPEND & & gspfnMyVerifyPwdProc = = NULL )
2004-01-17 21:34:54 +00:00
InterruptSaver ( ) ;
break ;
2006-12-29 16:35:33 +00:00
}
2006-04-13 04:21:23 +00:00
2006-12-29 16:35:33 +00:00
if ( WM_SETTIMER = = uMsg ) {
BOINCTRACE ( _T ( " CScreensaver::SaverProc Received WM_SETTIMER \n " ) ) ;
// All initialization messages have gone through. Allow
// 500ms of idle time, then proceed with initialization.
SetTimer ( hWnd , 1 , 500 , NULL ) ;
} else if ( WM_INTERRUPTSAVER = = uMsg ) {
BOINCTRACE ( _T ( " CScreensaver::SaverProc Received WM_INTERRUPTSAVER \n " ) ) ;
if ( hWnd = = m_Monitors [ 0 ] . hWnd ) {
InterruptSaver ( ) ;
}
2006-04-13 04:21:23 +00:00
2004-01-17 21:34:54 +00:00
}
2006-12-29 16:35:33 +00:00
2005-04-06 23:12:27 +00:00
return DefWindowProc ( hWnd , uMsg , wParam , lParam ) ;
2002-11-14 00:49:24 +00:00
}
2002-12-16 22:34:50 +00:00
2004-01-17 21:34:54 +00:00
2005-07-07 22:26:49 +00:00
INT_PTR CScreensaver : : ConfigureDialogProc ( HWND hwnd , UINT msg , WPARAM wParam , LPARAM UNUSED ( lParam ) ) {
2005-01-13 01:52:56 +00:00
DWORD screen_blank = 0 , blank_time = 0 ;
char buf [ 256 ] ;
int retval ;
switch ( msg ) {
case WM_INITDIALOG :
// make sure you check return value of registry queries
// in case the item in question doesn't happen to exist.
2005-04-06 23:12:27 +00:00
retval = UtilGetRegKey ( REG_BLANK_NAME , screen_blank ) ;
if ( retval < 0 ) {
screen_blank = 0 ;
}
CheckDlgButton ( hwnd , IDC_BLANK , screen_blank ) ;
2005-01-13 01:52:56 +00:00
2005-04-06 23:12:27 +00:00
retval = UtilGetRegKey ( REG_BLANK_TIME , blank_time ) ;
if ( retval < 0 ) { blank_time = 0 ; }
2005-01-13 01:52:56 +00:00
_ltot ( blank_time , buf , 10 ) ;
2005-04-06 23:12:27 +00:00
SetDlgItemText ( hwnd , IDC_BLANK_TIME , buf ) ;
2005-01-13 01:52:56 +00:00
return TRUE ;
case WM_COMMAND :
int id = LOWORD ( wParam ) ;
if ( id = = IDOK ) {
2005-04-06 23:12:27 +00:00
screen_blank = ( IsDlgButtonChecked ( hwnd , IDC_BLANK ) = = BST_CHECKED ) ;
UtilSetRegKey ( REG_BLANK_NAME , screen_blank ) ;
2005-01-13 01:52:56 +00:00
2005-04-06 23:12:27 +00:00
GetDlgItemText ( hwnd , IDC_BLANK_TIME , buf , 256 ) ;
blank_time = atoi ( buf ) ;
UtilSetRegKey ( REG_BLANK_TIME , blank_time ) ;
2005-01-13 01:52:56 +00:00
}
2005-04-06 23:12:27 +00:00
if ( id = = IDOK | | id = = IDCANCEL ) {
EndDialog ( hwnd , id ) ;
}
2005-01-13 01:52:56 +00:00
break ;
}
return FALSE ;
}
2005-04-06 23:12:27 +00:00
// This function forwards all window messages to SaverProc, which has
2005-01-13 01:52:56 +00:00
// access to the "this" pointer.
2005-04-06 23:12:27 +00:00
//
LRESULT CALLBACK CScreensaver : : SaverProcStub (
HWND hWnd , UINT uMsg , WPARAM wParam , LPARAM lParam
) {
2006-04-12 02:28:50 +00:00
return gspScreensaver - > SaverProc ( hWnd , uMsg , wParam , lParam ) ;
2005-01-13 01:52:56 +00:00
}
2005-04-06 23:12:27 +00:00
INT_PTR CALLBACK CScreensaver : : ConfigureDialogProcStub (
HWND hwndDlg , UINT uMsg , WPARAM wParam , LPARAM lParam
) {
2006-04-12 02:28:50 +00:00
return gspScreensaver - > ConfigureDialogProc ( hwndDlg , uMsg , wParam , lParam ) ;
2005-01-13 01:52:56 +00:00
}
2005-04-06 23:12:27 +00:00
VOID CScreensaver : : ShutdownSaver ( ) {
2004-01-17 21:34:54 +00:00
// Unflag screensaver running if in full on mode
2005-04-06 23:12:27 +00:00
if ( m_SaverMode = = sm_full ) {
2004-01-17 21:34:54 +00:00
BOOL bUnused ;
2005-04-06 23:12:27 +00:00
SystemParametersInfo ( SPI_SCREENSAVERRUNNING , FALSE , & bUnused , 0 ) ;
2004-01-17 21:34:54 +00:00
}
2007-08-16 23:09:03 +00:00
// Kill the currently executing graphics application
2007-10-05 13:28:11 +00:00
terminate_screensaver ( m_hGraphicsApplication , & m_running_result ) ;
2007-08-16 23:09:03 +00:00
2004-01-17 21:34:54 +00:00
// Post message to drop out of message loop
2005-05-13 00:33:04 +00:00
// This can be called from the data management thread, so specifically
// lookup and post to the primary window instead of calling PostQuitMessage
// since PostQuitMessage posts to the current threads message pump if it
// exists.
if ( m_Monitors [ 0 ] . hWnd ) {
PostMessage ( m_Monitors [ 0 ] . hWnd , WM_QUIT , 0 , 0 ) ;
}
2004-01-17 21:34:54 +00:00
}
2005-04-06 23:12:27 +00:00
// A message was received (mouse move, keydown, etc.) that may mean
2004-01-17 21:34:54 +00:00
// the screen saver should show the password dialog and/or shut down.
2005-04-06 23:12:27 +00:00
//
VOID CScreensaver : : InterruptSaver ( ) {
2004-01-17 21:34:54 +00:00
BOOL bPasswordOkay = FALSE ;
2006-04-13 08:37:25 +00:00
BOINCTRACE ( _T ( " CScreensaver::InterruptSaver Function Begin \n " ) ) ;
2006-04-13 00:28:31 +00:00
if ( m_SaverMode = = sm_test | | m_SaverMode = = sm_full & & ! m_bCheckingSaverPassword ) {
2005-04-06 23:12:27 +00:00
if ( m_bIs9x & & m_SaverMode = = sm_full ) {
2004-01-17 21:34:54 +00:00
// If no VerifyPassword function, then no password is set
// or we're not on 9x.
2006-04-13 00:50:41 +00:00
if ( gspfnMyVerifyPwdProc ) {
2006-04-13 08:37:25 +00:00
BOINCTRACE ( _T ( " CScreensaver::InterruptSaver Win9x Detected and Password Configured \n " ) ) ;
2004-01-17 21:34:54 +00:00
m_bCheckingSaverPassword = TRUE ;
2006-04-13 08:37:25 +00:00
BOINCTRACE ( _T ( " CScreensaver::InterruptSaver Calling VerifyScreenSavePwd \n " ) ) ;
2006-04-13 00:28:31 +00:00
bPasswordOkay = gspfnMyVerifyPwdProc ( m_hWnd ) ;
2006-04-13 08:37:25 +00:00
BOINCTRACE ( _T ( " CScreensaver::InterruptSaver Finished \n " ) ) ;
2004-01-17 21:34:54 +00:00
m_bCheckingSaverPassword = FALSE ;
2005-04-06 23:12:27 +00:00
if ( ! bPasswordOkay ) {
2004-01-17 21:34:54 +00:00
// Back to screen saving...
2006-04-13 08:37:25 +00:00
BOINCTRACE ( _T ( " CScreensaver::InterruptSaver Incorrect Password Given, Resetting m_dwSaverMouseMoveCount \n " ) ) ;
2005-04-06 23:12:27 +00:00
SetCursor ( NULL ) ;
2004-01-17 21:34:54 +00:00
m_dwSaverMouseMoveCount = 0 ;
return ;
}
}
}
ShutdownSaver ( ) ;
2006-04-13 08:37:25 +00:00
} else {
if ( m_bIs9x & & m_SaverMode = = sm_full & & m_bCheckingSaverPassword ) {
// Win9x sucks so bad the darn password dialog can get stuck behind the
// screensaver window. Which leaves the screensaver in a state where
// you have to reboot the machine.
HWND hwndPassword = FindWindow ( _T ( " #32770 " ) , _T ( " Windows Screen Saver " ) ) ;
HWND hwndForeWindow = GetForegroundWindow ( ) ;
if ( hwndPassword ) {
BOINCTRACE ( _T ( " CScreensaver::InterruptSaver Password Dialog Detected \n " ) ) ;
if ( hwndPassword ! = hwndForeWindow ) {
BOINCTRACE ( _T ( " CScreensaver::InterruptSaver Password Dialog is NOT the foreground window, bringing to foreground \n " ) ) ;
SetForegroundWindow ( hwndPassword ) ;
}
}
}
2004-01-17 21:34:54 +00:00
}
2006-04-13 08:37:25 +00:00
BOINCTRACE ( _T ( " CScreensaver::InterruptSaver Function End \n " ) ) ;
2004-01-17 21:34:54 +00:00
}
2006-04-13 00:50:41 +00:00
2005-04-06 23:12:27 +00:00
// Update the box that shows the error message
//
VOID CScreensaver : : UpdateErrorBox ( ) {
2004-01-17 21:34:54 +00:00
INTERNALMONITORINFO * pMonitorInfo ;
HWND hwnd ;
RECT rcBounds ;
static DWORD dwTimeLast = 0 ;
DWORD dwTimeNow ;
FLOAT fTimeDelta ;
2004-11-17 09:27:06 +00:00
2004-01-17 21:34:54 +00:00
// Update timing to determine how much to move error box
2005-04-06 23:12:27 +00:00
if ( dwTimeLast = = 0 ) {
2004-01-17 21:34:54 +00:00
dwTimeLast = timeGetTime ( ) ;
2005-04-06 23:12:27 +00:00
}
2007-08-20 19:54:42 +00:00
2004-01-17 21:34:54 +00:00
dwTimeNow = timeGetTime ( ) ;
2006-07-25 10:19:27 +00:00
fTimeDelta = ( FLOAT ) ( dwTimeNow - dwTimeLast ) / 10000.0f ;
2004-01-17 21:34:54 +00:00
dwTimeLast = dwTimeNow ;
2005-04-06 23:12:27 +00:00
for ( DWORD iMonitor = 0 ; iMonitor < m_dwNumMonitors ; iMonitor + + ) {
2004-01-17 21:34:54 +00:00
pMonitorInfo = & m_Monitors [ iMonitor ] ;
hwnd = pMonitorInfo - > hWnd ;
2005-04-06 23:12:27 +00:00
if ( hwnd = = NULL )
2004-01-17 21:34:54 +00:00
continue ;
2005-04-06 23:12:27 +00:00
if ( m_SaverMode = = sm_full ) {
2004-01-17 21:34:54 +00:00
rcBounds = pMonitorInfo - > rcScreen ;
2005-04-06 23:12:27 +00:00
ScreenToClient ( hwnd , ( POINT * ) & rcBounds . left ) ;
ScreenToClient ( hwnd , ( POINT * ) & rcBounds . right ) ;
} else {
2004-01-17 21:34:54 +00:00
rcBounds = m_rcRenderTotal ;
}
2005-04-06 23:12:27 +00:00
if ( pMonitorInfo - > widthError = = 0 ) {
if ( m_SaverMode = = sm_preview ) {
2004-01-17 21:34:54 +00:00
pMonitorInfo - > widthError = ( float ) ( rcBounds . right - rcBounds . left ) ;
pMonitorInfo - > heightError = ( float ) ( rcBounds . bottom - rcBounds . top ) ;
pMonitorInfo - > xError = 0.0f ;
pMonitorInfo - > yError = 0.0f ;
pMonitorInfo - > xVelError = 0.0f ;
pMonitorInfo - > yVelError = 0.0f ;
2005-04-06 23:12:27 +00:00
InvalidateRect ( hwnd , NULL , FALSE ) ; // Invalidate the hwnd so it gets drawn
UpdateWindow ( hwnd ) ;
} else {
2007-10-02 21:44:14 +00:00
pMonitorInfo - > widthError = 454 ;
pMonitorInfo - > heightError = 320 ;
2004-01-17 21:34:54 +00:00
pMonitorInfo - > xError = ( rcBounds . right + rcBounds . left - pMonitorInfo - > widthError ) / 2.0f ;
pMonitorInfo - > yError = ( rcBounds . bottom + rcBounds . top - pMonitorInfo - > heightError ) / 2.0f ;
pMonitorInfo - > xVelError = ( rcBounds . right - rcBounds . left ) / 10.0f ;
2005-04-05 10:23:15 +00:00
pMonitorInfo - > yVelError = ( rcBounds . bottom - rcBounds . top ) / 20.0f ;
}
2005-04-06 23:12:27 +00:00
} else {
if ( m_SaverMode ! = sm_preview ) {
2005-04-05 10:23:15 +00:00
RECT rcOld ;
RECT rcNew ;
2005-02-03 01:55:34 +00:00
2005-04-06 23:12:27 +00:00
SetRect ( & rcOld , ( INT ) pMonitorInfo - > xError , ( INT ) pMonitorInfo - > yError ,
2005-04-05 10:23:15 +00:00
( INT ) ( pMonitorInfo - > xError + pMonitorInfo - > widthError ) ,
2005-04-06 23:12:27 +00:00
( INT ) ( pMonitorInfo - > yError + pMonitorInfo - > heightError ) ) ;
2005-02-03 01:55:34 +00:00
2005-04-05 10:23:15 +00:00
// Update rect velocity
2005-04-06 23:12:27 +00:00
if ( ( pMonitorInfo - > xError + pMonitorInfo - > xVelError * fTimeDelta +
2005-04-05 10:23:15 +00:00
pMonitorInfo - > widthError > rcBounds . right & & pMonitorInfo - > xVelError > 0.0f ) | |
( pMonitorInfo - > xError + pMonitorInfo - > xVelError * fTimeDelta <
2005-04-06 23:12:27 +00:00
rcBounds . left & & pMonitorInfo - > xVelError < 0.0f )
) {
2005-04-05 10:23:15 +00:00
pMonitorInfo - > xVelError = - pMonitorInfo - > xVelError ;
2005-02-03 01:55:34 +00:00
}
2005-04-06 23:12:27 +00:00
if ( ( pMonitorInfo - > yError + pMonitorInfo - > yVelError * fTimeDelta +
2005-04-05 10:23:15 +00:00
pMonitorInfo - > heightError > rcBounds . bottom & & pMonitorInfo - > yVelError > 0.0f ) | |
( pMonitorInfo - > yError + pMonitorInfo - > yVelError * fTimeDelta <
2005-04-06 23:12:27 +00:00
rcBounds . top & & pMonitorInfo - > yVelError < 0.0f )
) {
2005-04-05 10:23:15 +00:00
pMonitorInfo - > yVelError = - pMonitorInfo - > yVelError ;
2005-02-03 01:55:34 +00:00
}
2005-04-05 10:23:15 +00:00
// Update rect position
pMonitorInfo - > xError + = pMonitorInfo - > xVelError * fTimeDelta ;
pMonitorInfo - > yError + = pMonitorInfo - > yVelError * fTimeDelta ;
2005-04-06 23:12:27 +00:00
SetRect ( & rcNew , ( INT ) pMonitorInfo - > xError , ( INT ) pMonitorInfo - > yError ,
2005-04-05 10:23:15 +00:00
( INT ) ( pMonitorInfo - > xError + pMonitorInfo - > widthError ) ,
2005-04-06 23:12:27 +00:00
( INT ) ( pMonitorInfo - > yError + pMonitorInfo - > heightError ) ) ;
2004-01-17 21:34:54 +00:00
2007-08-20 19:54:42 +00:00
if ( ( dwTimeNow - pMonitorInfo - > dwTimeLastUpdate ) > 1000 )
2006-07-25 10:19:27 +00:00
{
pMonitorInfo - > dwTimeLastUpdate = dwTimeNow ;
InvalidateRect ( hwnd , NULL , TRUE ) ;
2005-04-06 23:12:27 +00:00
UpdateWindow ( hwnd ) ;
2006-07-25 10:19:27 +00:00
}
2005-04-05 10:23:15 +00:00
}
2004-01-17 21:34:54 +00:00
}
}
}
2006-07-25 10:19:27 +00:00
VOID CScreensaver : : DoPaint ( HWND hwnd , HDC hdc , LPPAINTSTRUCT lpps ) {
2005-07-04 21:54:24 +00:00
DWORD iMonitor = 0 ;
2006-07-25 10:19:27 +00:00
INTERNALMONITORINFO * pMonitorInfo = NULL ;
HMONITOR hMonitor = MonitorFromWindow ( hwnd , MONITOR_DEFAULTTONEAREST ) ;
2005-07-04 21:54:24 +00:00
for ( iMonitor = 0 ; iMonitor < m_dwNumMonitors ; iMonitor + + ) {
2004-01-17 21:34:54 +00:00
pMonitorInfo = & m_Monitors [ iMonitor ] ;
2005-04-06 23:12:27 +00:00
if ( pMonitorInfo - > hMonitor = = hMonitor )
2004-01-17 21:34:54 +00:00
break ;
}
2005-04-06 23:12:27 +00:00
if ( iMonitor = = m_dwNumMonitors ) {
2004-01-17 21:34:54 +00:00
return ;
2005-04-06 23:12:27 +00:00
}
2004-01-17 21:34:54 +00:00
2006-07-25 10:19:27 +00:00
// Retrieve the latest piece of error information
2005-04-05 10:23:15 +00:00
BOOL bErrorMode ;
HRESULT hrError ;
TCHAR szError [ 400 ] ;
2006-07-25 10:19:27 +00:00
GetError ( bErrorMode , hrError , szError , sizeof ( szError ) / sizeof ( TCHAR ) ) ;
// Start drawing the goods
2004-01-17 21:34:54 +00:00
RECT rc ;
RECT rc2 ;
RECT rcOrginal ;
int iTextHeight ;
2005-04-06 23:12:27 +00:00
static HBRUSH hbrushBlack = ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ;
static HBRUSH hbrushRed = ( HBRUSH ) CreateSolidBrush ( RGB ( 255 , 0 , 0 ) ) ;
static HBITMAP hbmp = LoadBitmap ( m_hInstance , MAKEINTRESOURCE ( IDB_BOINCSPLAT ) ) ;
2004-01-17 21:34:54 +00:00
2006-07-25 10:19:27 +00:00
// Start off with a black screen and then draw on top of it.
FillRect ( hdc , & lpps - > rcPaint , hbrushBlack ) ;
2005-04-05 10:23:15 +00:00
2005-02-06 09:34:38 +00:00
// If the screensaver has switched to a blanked state or not in an error mode,
// we should exit here so the screen has been erased to black.
2007-08-14 17:23:30 +00:00
if ( ! bErrorMode ) {
2005-02-06 09:34:38 +00:00
return ;
}
2005-04-06 23:12:27 +00:00
SetRect ( & rc , ( INT ) pMonitorInfo - > xError , ( INT ) pMonitorInfo - > yError ,
2004-01-17 21:34:54 +00:00
( INT ) ( pMonitorInfo - > xError + pMonitorInfo - > widthError ) ,
2005-04-06 23:12:27 +00:00
( INT ) ( pMonitorInfo - > yError + pMonitorInfo - > heightError )
) ;
2007-10-02 21:44:14 +00:00
// This fill rect is useful when testing
// FillRect(hdc, &rc, hbrushRed);
2006-07-25 10:19:27 +00:00
rcOrginal = rc ;
2004-01-17 21:34:54 +00:00
// Draw the bitmap rectangle and copy the bitmap into
// it. the bitmap is centered in the rectangle by adding 2
// to the left and top coordinates of the bitmap rectangle,
// and subtracting 4 from the right and bottom coordinates.
2007-10-02 21:44:14 +00:00
BITMAP bm ;
GetObject ( hbmp , sizeof ( BITMAP ) , ( LPSTR ) & bm ) ;
long left = rc . left + ( pMonitorInfo - > widthError - 4 - bm . bmWidth ) / 2 ;
long top = rc . top + 2 ;
DrawTransparentBitmap ( hdc , hbmp , left , top , RGB ( 255 , 0 , 255 ) ) ;
2004-01-17 21:34:54 +00:00
// Draw text in the center of the frame
SetBkColor ( hdc , RGB ( 0 , 0 , 0 ) ) ; // Black
SetTextColor ( hdc , RGB ( 255 , 255 , 255 ) ) ; // Red
2007-10-02 21:44:14 +00:00
// Set font
HFONT hf ;
hf = CreateFont ( 0 , 0 , 0 , 0 , FW_DONTCARE , FALSE , FALSE , 0 , ANSI_CHARSET , OUT_DEFAULT_PRECIS , CLIP_DEFAULT_PRECIS , DEFAULT_QUALITY , DEFAULT_PITCH | FF_SWISS , " Arial Narrow " ) ;
if ( hf )
{
SelectObject ( hdc , hf ) ;
}
2004-01-17 21:34:54 +00:00
rc2 = rc ;
2005-04-06 23:12:27 +00:00
iTextHeight = DrawText ( hdc , szError , - 1 , & rc , DT_CENTER | DT_CALCRECT ) ;
2004-01-17 21:34:54 +00:00
rc = rc2 ;
2007-10-02 21:44:14 +00:00
rc2 . top + = bm . bmHeight + 20 ;
2005-04-06 23:12:27 +00:00
DrawText ( hdc , szError , - 1 , & rc2 , DT_CENTER ) ;
2004-01-17 21:34:54 +00:00
}
2005-04-06 23:12:27 +00:00
// Draws a bitmap on the screen with a transparent background.
2004-01-18 19:36:50 +00:00
// Code orginally from Microsoft Knowledge Base Article - 79212
2005-04-06 23:12:27 +00:00
//
void CScreensaver : : DrawTransparentBitmap (
HDC hdc , HBITMAP hBitmap , LONG xStart , LONG yStart ,
COLORREF cTransparentColor
) {
BITMAP bm ;
COLORREF cColor ;
HBITMAP bmAndBack , bmAndObject , bmAndMem , bmSave ;
HBITMAP bmBackOld , bmObjectOld , bmMemOld , bmSaveOld ;
HDC hdcMem , hdcBack , hdcObject , hdcTemp , hdcSave ;
POINT ptSize ;
hdcTemp = CreateCompatibleDC ( hdc ) ;
SelectObject ( hdcTemp , hBitmap ) ; // Select the bitmap
GetObject ( hBitmap , sizeof ( BITMAP ) , ( LPSTR ) & bm ) ;
ptSize . x = bm . bmWidth ; // Get width of bitmap
ptSize . y = bm . bmHeight ; // Get height of bitmap
DPtoLP ( hdcTemp , & ptSize , 1 ) ; // Convert from device
2004-01-18 19:36:50 +00:00
// to logical points
2005-04-06 23:12:27 +00:00
// Create some DCs to hold temporary data.
hdcBack = CreateCompatibleDC ( hdc ) ;
hdcObject = CreateCompatibleDC ( hdc ) ;
hdcMem = CreateCompatibleDC ( hdc ) ;
hdcSave = CreateCompatibleDC ( hdc ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Create a bitmap for each DC. DCs are required for a number of
// GDI functions.
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Monochrome DC
bmAndBack = CreateBitmap ( ptSize . x , ptSize . y , 1 , 1 , NULL ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Monochrome DC
bmAndObject = CreateBitmap ( ptSize . x , ptSize . y , 1 , 1 , NULL ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
bmAndMem = CreateCompatibleBitmap ( hdc , ptSize . x , ptSize . y ) ;
bmSave = CreateCompatibleBitmap ( hdc , ptSize . x , ptSize . y ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Each DC must select a bitmap object to store pixel data.
bmBackOld = ( HBITMAP ) SelectObject ( hdcBack , bmAndBack ) ;
bmObjectOld = ( HBITMAP ) SelectObject ( hdcObject , bmAndObject ) ;
bmMemOld = ( HBITMAP ) SelectObject ( hdcMem , bmAndMem ) ;
bmSaveOld = ( HBITMAP ) SelectObject ( hdcSave , bmSave ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Set proper mapping mode.
SetMapMode ( hdcTemp , GetMapMode ( hdc ) ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Save the bitmap sent here, because it will be overwritten.
BitBlt ( hdcSave , 0 , 0 , ptSize . x , ptSize . y , hdcTemp , 0 , 0 , SRCCOPY ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Set the background color of the source DC to the color.
// contained in the parts of the bitmap that should be transparent
cColor = SetBkColor ( hdcTemp , cTransparentColor ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Create the object mask for the bitmap by performing a BitBlt
// from the source bitmap to a monochrome bitmap.
BitBlt ( hdcObject , 0 , 0 , ptSize . x , ptSize . y , hdcTemp , 0 , 0 , SRCCOPY ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Set the background color of the source DC back to the original
// color.
SetBkColor ( hdcTemp , cColor ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Create the inverse of the object mask.
BitBlt ( hdcBack , 0 , 0 , ptSize . x , ptSize . y , hdcObject , 0 , 0 , NOTSRCCOPY ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Copy the background of the main DC to the destination.
BitBlt ( hdcMem , 0 , 0 , ptSize . x , ptSize . y , hdc , xStart , yStart , SRCCOPY ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Mask out the places where the bitmap will be placed.
BitBlt ( hdcMem , 0 , 0 , ptSize . x , ptSize . y , hdcObject , 0 , 0 , SRCAND ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Mask out the transparent colored pixels on the bitmap.
BitBlt ( hdcTemp , 0 , 0 , ptSize . x , ptSize . y , hdcBack , 0 , 0 , SRCAND ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// XOR the bitmap with the background on the destination DC.
BitBlt ( hdcMem , 0 , 0 , ptSize . x , ptSize . y , hdcTemp , 0 , 0 , SRCPAINT ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Copy the destination to the screen.
BitBlt ( hdc , xStart , yStart , ptSize . x , ptSize . y , hdcMem , 0 , 0 , SRCCOPY ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Place the original bitmap back into the bitmap sent here.
BitBlt ( hdcTemp , 0 , 0 , ptSize . x , ptSize . y , hdcSave , 0 , 0 , SRCCOPY ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Delete the memory bitmaps.
DeleteObject ( SelectObject ( hdcBack , bmBackOld ) ) ;
DeleteObject ( SelectObject ( hdcObject , bmObjectOld ) ) ;
DeleteObject ( SelectObject ( hdcMem , bmMemOld ) ) ;
DeleteObject ( SelectObject ( hdcSave , bmSaveOld ) ) ;
2004-01-18 19:36:50 +00:00
2005-04-06 23:12:27 +00:00
// Delete the memory DCs.
DeleteDC ( hdcMem ) ;
DeleteDC ( hdcBack ) ;
DeleteDC ( hdcObject ) ;
DeleteDC ( hdcSave ) ;
DeleteDC ( hdcTemp ) ;
2004-01-18 19:36:50 +00:00
}
2004-01-19 19:45:52 +00:00
2006-07-25 10:19:27 +00:00
VOID CScreensaver : : ChangePassword ( ) {
// Load the password change DLL
HINSTANCE mpr = LoadLibrary ( _T ( " MPR.DLL " ) ) ;
if ( mpr ! = NULL ) {
// Grab the password change function from it
typedef DWORD ( PASCAL * PWCHGPROC ) ( LPCSTR , HWND , DWORD , LPVOID ) ;
PWCHGPROC pwd = ( PWCHGPROC ) GetProcAddress ( mpr , " PwdChangePasswordA " ) ;
// Do the password change
if ( pwd ! = NULL ) {
pwd ( " SCRSAVE " , m_hWndParent , 0 , NULL ) ;
}
// Free the library
FreeLibrary ( mpr ) ;
}
}
2005-01-02 18:29:53 +00:00
const char * BOINC_RCSID_116268c72f = " $Id$ " ;