From 6049c6756f0c237416b084d0c99bff361577ec02 Mon Sep 17 00:00:00 2001 From: Rom Walton Date: Wed, 9 Feb 2005 01:14:14 +0000 Subject: [PATCH] *** empty log message *** svn path=/trunk/boinc/; revision=5368 --- checkin_notes | 27 +++ clientgui/BOINCGUIApp.cpp | 1 + clientgui/BOINCTaskBar.cpp | 46 ++++- clientgui/BOINCTaskBar.h | 3 + clientgui/msw/taskbarex.cpp | 153 +++++++++++------ clientgui/msw/taskbarex.h | 7 +- win_build/installerv2/BOINC.ism | Bin 205312 -> 205560 bytes .../ShutdownBOINCManager.cpp | 145 ++++++++++++++++ .../ShutdownBOINCManager.def | 8 + .../ShutdownBOINCManager.sln | 21 +++ .../ShutdownBOINCManager.vcproj | 161 ++++++++++++++++++ .../src/ShutdownBOINCManager/stdafx.cpp | 10 ++ .../Windows/src/ShutdownBOINCManager/stdafx.h | 22 +++ .../redist/Windows/x86/shutdown.dll | Bin 0 -> 45056 bytes 14 files changed, 541 insertions(+), 63 deletions(-) create mode 100644 win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.cpp create mode 100644 win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.def create mode 100644 win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.sln create mode 100644 win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.vcproj create mode 100644 win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/stdafx.cpp create mode 100644 win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/stdafx.h create mode 100644 win_build/installerv2/redist/Windows/x86/shutdown.dll diff --git a/checkin_notes b/checkin_notes index f953f35437..5726c8fb67 100755 --- a/checkin_notes +++ b/checkin_notes @@ -24291,3 +24291,30 @@ David 8 Feb 2005 setup_project.py tools/ make_project + +Rom 8 Feb 2005 + - Bug Fix: Add the ability for setup to shutdown any running instances + of the BOINC Manager during install and uninstall. + - Bug Fix: Change "Launch the program" to "Launch the BOINC Manager" + - Bug Fix: Fix a number of event bubble up issues with the base + wxTaskBarEx class, the sample format provided with the wxWidget + framework leads down the wrong path if you try to extend the class. + - Bug Fix: Add another custom action dll to do the actual shutdown + of the BOINC Manager + + clientgui/ + BOINCGUIApp.cpp + BOINCTaskBar.cpp, .h + clientgui/msw/ + taskbarex.cpp, .h + win_build/installerv2/ + BOINC.ism + win_build/installerv2/Windows/src/ShutdownBOINCManager + ShutdownBOINCManager.cpp ( added ) + ShutdownBOINCManager.def ( added ) + ShutdownBOINCManager.sln ( added ) + ShutdownBOINCManager.vcproj ( added ) + stdafx.cpp, .h ( added ) + win_build/installerv2/Windows/x86/ + shutdown.dll + \ No newline at end of file diff --git a/clientgui/BOINCGUIApp.cpp b/clientgui/BOINCGUIApp.cpp index ea6bfb1b3e..8cc57d7ca6 100644 --- a/clientgui/BOINCGUIApp.cpp +++ b/clientgui/BOINCGUIApp.cpp @@ -99,6 +99,7 @@ bool CBOINCGUIApp::OnInit() wxLog::SetActiveTarget(m_pLog); m_pLog->AddTraceMask( wxT("Function Start/End") ); + m_pLog->AddTraceMask( wxT("Function Status") ); // Enable the in memory virtual file system for // storing images diff --git a/clientgui/BOINCTaskBar.cpp b/clientgui/BOINCTaskBar.cpp index 5494e92b1a..39965fed70 100644 --- a/clientgui/BOINCTaskBar.cpp +++ b/clientgui/BOINCTaskBar.cpp @@ -38,6 +38,11 @@ BEGIN_EVENT_TABLE (CTaskBarIcon, wxTaskBarIconEx) EVT_MENU_RANGE(ID_TB_NETWORKRUNALWAYS, ID_TB_NETWORKSUSPEND, CTaskBarIcon::OnNetworkSelection) EVT_MENU(wxID_ABOUT, CTaskBarIcon::OnAbout) EVT_MENU(wxID_EXIT, CTaskBarIcon::OnExit) + +#ifdef __WXMSW__ + EVT_TASKBAR_SHUTDOWN(CTaskBarIcon::OnShutdown) +#endif + EVT_IDLE(CTaskBarIcon::OnIdle) EVT_CLOSE(CTaskBarIcon::OnClose) EVT_TASKBAR_MOVE(CTaskBarIcon::OnMouseMove) @@ -53,7 +58,7 @@ END_EVENT_TABLE () CTaskBarIcon::CTaskBarIcon() : - wxTaskBarIconEx() + wxTaskBarIconEx( wxT("BOINCManagerSystray") ) { m_iconTaskBarIcon = wxIcon( boinc_xpm ); m_dtLastHoverDetected = wxDateTime( (time_t)0 ); @@ -146,19 +151,40 @@ void CTaskBarIcon::OnAbout( wxCommandEvent& WXUNUSED(event) ) } -void CTaskBarIcon::OnExit( wxCommandEvent& WXUNUSED(event) ) +void CTaskBarIcon::OnExit( wxCommandEvent& event ) { - ResetTaskBar(); + wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnExit - Function Begin")); - CMainFrame* pFrame = wxGetApp().GetFrame(); - wxASSERT(NULL != pFrame); - wxASSERT(wxDynamicCast(pFrame, CMainFrame)); + wxCloseEvent eventClose; - if ( NULL != pFrame ) - pFrame->Close(true); + OnClose( eventClose ); + + if ( eventClose.GetSkipped() ) event.Skip(); + + wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnExit - Function End")); } +#ifdef __WXMSW__ + + +void CTaskBarIcon::OnShutdown( wxTaskBarIconExEvent& event ) +{ + wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnShutdown - Function Begin")); + + wxCloseEvent eventClose; + + OnClose( eventClose ); + + if ( eventClose.GetSkipped() ) event.Skip(); + + wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnShutdown - Function End")); +} + + +#endif + + void CTaskBarIcon::OnIdle( wxIdleEvent& event ) { wxGetApp().UpdateSystemIdleDetection(); @@ -168,6 +194,8 @@ void CTaskBarIcon::OnIdle( wxIdleEvent& event ) void CTaskBarIcon::OnClose( wxCloseEvent& event ) { + wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnClose - Function Begin")); + ResetTaskBar(); CMainFrame* pFrame = wxGetApp().GetFrame(); @@ -178,6 +206,8 @@ void CTaskBarIcon::OnClose( wxCloseEvent& event ) pFrame->Close(true); event.Skip(); + + wxLogTrace(wxT("Function Start/End"), wxT("CTaskBarIcon::OnClose - Function End")); } diff --git a/clientgui/BOINCTaskBar.h b/clientgui/BOINCTaskBar.h index c3023f69bc..cbdf417cc6 100644 --- a/clientgui/BOINCTaskBar.h +++ b/clientgui/BOINCTaskBar.h @@ -44,6 +44,9 @@ public: void OnNetworkSelection( wxCommandEvent& event ); void OnAbout( wxCommandEvent& event ); void OnExit( wxCommandEvent& event ); +#ifdef __WXMSW__ + void OnShutdown( wxTaskBarIconExEvent& event ); +#endif void OnIdle( wxIdleEvent& event ); void OnClose( wxCloseEvent& event ); diff --git a/clientgui/msw/taskbarex.cpp b/clientgui/msw/taskbarex.cpp index 1ad7b35898..3c198d2d5f 100644 --- a/clientgui/msw/taskbarex.cpp +++ b/clientgui/msw/taskbarex.cpp @@ -20,7 +20,10 @@ LRESULT APIENTRY wxTaskBarIconExWindowProc( HWND hWnd, unsigned msg, UINT wParam, LONG lParam ); wxChar *wxTaskBarExWindowClass = (wxChar*) wxT("wxTaskBarExWindowClass"); +wxChar *wxTaskBarExWindow = (wxChar*) wxT("wxTaskBarExWindow"); + const UINT WM_TASKBARCREATED = ::RegisterWindowMessage(wxT("TaskbarCreated")); +const UINT WM_TASKBARSHUTDOWN = ::RegisterWindowMessage(wxT("TaskbarShutdown")); wxList wxTaskBarIconEx::sm_taskBarIcons; bool wxTaskBarIconEx::sm_registeredClass = FALSE; @@ -34,6 +37,7 @@ DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_SHOW ) DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_HIDE ) DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_TIMEOUT ) DEFINE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_USERCLICK ) +DEFINE_EVENT_TYPE( wxEVT_TASKBAR_SHUTDOWN ) IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIconEx, wxEvtHandler) @@ -51,7 +55,18 @@ wxTaskBarIconEx::wxTaskBarIconEx(void) AddObject(this); if (RegisterWindowClass()) - m_hWnd = CreateTaskBarWindow(); + m_hWnd = CreateTaskBarWindow( wxTaskBarExWindow ); +} + +wxTaskBarIconEx::wxTaskBarIconEx( wxChar* szWindowTitle ) +{ + m_hWnd = 0; + m_iconAdded = FALSE; + + AddObject(this); + + if (RegisterWindowClass()) + m_hWnd = CreateTaskBarWindow( szWindowTitle ); } wxTaskBarIconEx::~wxTaskBarIconEx(void) @@ -73,8 +88,12 @@ wxTaskBarIconEx::~wxTaskBarIconEx(void) // Events void wxTaskBarIconEx::OnClose(wxCloseEvent& event) { + wxLogTrace(wxT("Function Start/End"), wxT("wxTaskBarIconEx::OnClose - Function Begin")); + ::DestroyWindow((HWND) m_hWnd); m_hWnd = 0; + + wxLogTrace(wxT("Function Start/End"), wxT("wxTaskBarIconEx::OnClose - Function End")); } void wxTaskBarIconEx::OnTaskBarCreated(wxTaskBarIconExEvent& event) @@ -293,12 +312,12 @@ bool wxTaskBarIconEx::RegisterWindowClass() return( (rc != 0) ); } -WXHWND wxTaskBarIconEx::CreateTaskBarWindow() +WXHWND wxTaskBarIconEx::CreateTaskBarWindow( wxChar* szWindowTitle ) { HINSTANCE hInstance = GetModuleHandle(NULL); HWND hWnd = CreateWindowEx (0, wxTaskBarExWindowClass, - wxT("wxTaskBarExWindow"), + szWindowTitle, WS_OVERLAPPED, 0, 0, @@ -327,82 +346,108 @@ bool wxTaskBarIconEx::IsBalloonsSupported() long wxTaskBarIconEx::WindowProc( WXHWND hWnd, unsigned int msg, unsigned int wParam, long lParam ) { + wxLogTrace(wxT("Function Start/End"), wxT("wxTaskBarIconEx::WindowProc - Function Begin")); + wxEventType eventType = 0; + long lReturnValue = 0; - if (msg != sm_taskbarMsg) - return DefWindowProc((HWND) hWnd, msg, wParam, lParam); - - switch (lParam) + if ( WM_CLOSE == msg ) { - case WM_LBUTTONDOWN: - eventType = wxEVT_TASKBAR_LEFT_DOWN; - break; + wxLogTrace(wxT("Function Status"), wxT("wxTaskBarIconEx::WindowProc - WM_CLOSE Detected")); + + wxCloseEvent eventClose(wxEVT_CLOSE_WINDOW, hWnd); + ProcessEvent(eventClose); - case WM_LBUTTONUP: - eventType = wxEVT_TASKBAR_LEFT_UP; - break; + if ( !eventClose.GetSkipped() ) + lReturnValue = DefWindowProc((HWND) hWnd, msg, wParam, lParam); + else + lReturnValue = 0; + } + else if ( WM_TASKBARCREATED == msg ) + { + wxLogTrace(wxT("Function Status"), wxT("wxTaskBarIconEx::WindowProc - WM_TASKBARCREATED Detected")); + eventType = wxEVT_TASKBAR_CREATED; + } + else if ( WM_TASKBARSHUTDOWN == msg ) + { + wxLogTrace(wxT("Function Status"), wxT("wxTaskBarIconEx::WindowProc - WM_TASKBARSHUTDOWN Detected")); + eventType = wxEVT_TASKBAR_SHUTDOWN; + } + if (msg != sm_taskbarMsg) + lReturnValue = DefWindowProc((HWND) hWnd, msg, wParam, lParam); - case WM_RBUTTONDOWN: - eventType = wxEVT_TASKBAR_RIGHT_DOWN; - break; + if ( 0 == eventType ) + { + switch (lParam) + { + case WM_LBUTTONDOWN: + eventType = wxEVT_TASKBAR_LEFT_DOWN; + break; - case WM_RBUTTONUP: - eventType = wxEVT_TASKBAR_RIGHT_UP; - break; + case WM_LBUTTONUP: + eventType = wxEVT_TASKBAR_LEFT_UP; + break; - case WM_LBUTTONDBLCLK: - eventType = wxEVT_TASKBAR_LEFT_DCLICK; - break; + case WM_RBUTTONDOWN: + eventType = wxEVT_TASKBAR_RIGHT_DOWN; + break; - case WM_RBUTTONDBLCLK: - eventType = wxEVT_TASKBAR_RIGHT_DCLICK; - break; + case WM_RBUTTONUP: + eventType = wxEVT_TASKBAR_RIGHT_UP; + break; - case WM_MOUSEMOVE: - eventType = wxEVT_TASKBAR_MOVE; - break; + case WM_LBUTTONDBLCLK: + eventType = wxEVT_TASKBAR_LEFT_DCLICK; + break; - case WM_CONTEXTMENU: - eventType = wxEVT_TASKBAR_CONTEXT_MENU; - break; + case WM_RBUTTONDBLCLK: + eventType = wxEVT_TASKBAR_RIGHT_DCLICK; + break; - case NIN_SELECT: - eventType = wxEVT_TASKBAR_SELECT; - break; + case WM_MOUSEMOVE: + eventType = wxEVT_TASKBAR_MOVE; + break; - case NIN_KEYSELECT: - eventType = wxEVT_TASKBAR_KEY_SELECT; - break; + case WM_CONTEXTMENU: + eventType = wxEVT_TASKBAR_CONTEXT_MENU; + break; - case NIN_BALLOONSHOW: - eventType = wxEVT_TASKBAR_BALLOON_SHOW; - break; + case NIN_SELECT: + eventType = wxEVT_TASKBAR_SELECT; + break; - case NIN_BALLOONHIDE: - eventType = wxEVT_TASKBAR_BALLOON_HIDE; - break; + case NIN_KEYSELECT: + eventType = wxEVT_TASKBAR_KEY_SELECT; + break; - case NIN_BALLOONTIMEOUT: - eventType = wxEVT_TASKBAR_BALLOON_TIMEOUT; - break; + case NIN_BALLOONSHOW: + eventType = wxEVT_TASKBAR_BALLOON_SHOW; + break; - case NIN_BALLOONUSERCLICK: - eventType = wxEVT_TASKBAR_BALLOON_USERCLICK; - break; + case NIN_BALLOONHIDE: + eventType = wxEVT_TASKBAR_BALLOON_HIDE; + break; - default: - if ( WM_TASKBARCREATED == lParam ) - eventType = wxEVT_TASKBAR_CREATED; - break; + case NIN_BALLOONTIMEOUT: + eventType = wxEVT_TASKBAR_BALLOON_TIMEOUT; + break; + + case NIN_BALLOONUSERCLICK: + eventType = wxEVT_TASKBAR_BALLOON_USERCLICK; + break; + } } if (eventType) { wxTaskBarIconExEvent event(eventType, this); ProcessEvent(event); + + lReturnValue = 0; } - return 0; + wxLogTrace(wxT("Function Start/End"), wxT("wxTaskBarIconEx::WindowProc - Function End")); + return lReturnValue; } LRESULT APIENTRY wxTaskBarIconExWindowProc( HWND hWnd, unsigned msg, UINT wParam, LONG lParam ) diff --git a/clientgui/msw/taskbarex.h b/clientgui/msw/taskbarex.h index 7607b05312..dc2413f137 100644 --- a/clientgui/msw/taskbarex.h +++ b/clientgui/msw/taskbarex.h @@ -26,7 +26,10 @@ class wxTaskBarIconExEvent; class wxTaskBarIconEx: public wxEvtHandler { DECLARE_DYNAMIC_CLASS(wxTaskBarIconEx) public: + wxTaskBarIconEx(void); + wxTaskBarIconEx( wxChar* szWindowTitle ); + virtual ~wxTaskBarIconEx(void); enum ICONTYPES @@ -69,7 +72,7 @@ public: static void AddObject(wxTaskBarIconEx* obj); static void RemoveObject(wxTaskBarIconEx* obj); static bool RegisterWindowClass(); - static WXHWND CreateTaskBarWindow(); + static WXHWND CreateTaskBarWindow( wxChar* szWindowTitle ); static bool IsBalloonsSupported(); long WindowProc( WXHWND hWnd, unsigned int msg, unsigned int wParam, long lParam ); @@ -114,6 +117,7 @@ DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_SHOW, 1561 ) DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_HIDE, 1562 ) DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_TIMEOUT, 1563 ) DECLARE_EVENT_TYPE( wxEVT_TASKBAR_BALLOON_USERCLICK, 1564 ) +DECLARE_EVENT_TYPE( wxEVT_TASKBAR_SHUTDOWN, 1565 ) END_DECLARE_EVENT_TYPES() #define EVT_TASKBAR_CREATED(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_TASKBAR_CREATED, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL), @@ -124,6 +128,7 @@ END_DECLARE_EVENT_TYPES() #define EVT_TASKBAR_BALLOON_HIDE(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_TASKBAR_BALLOON_HIDE, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL), #define EVT_TASKBAR_BALLOON_TIMEOUT(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_TASKBAR_BALLOON_TIMEOUT, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL), #define EVT_TASKBAR_CONTEXT_USERCLICK(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_TASKBAR_BALLOON_USERCLICK, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL), +#define EVT_TASKBAR_SHUTDOWN(fn) DECLARE_EVENT_TABLE_ENTRY(wxEVT_TASKBAR_SHUTDOWN, -1, -1, (wxObjectEventFunction) (wxEventFunction) &fn, NULL), #endif diff --git a/win_build/installerv2/BOINC.ism b/win_build/installerv2/BOINC.ism index bc754e74957fd6a55edec19dc054f43ba3fc578c..e72e61ee1f9a661ddc0dbfabfdb80bf7caf4f1eb 100644 GIT binary patch delta 1240 zcmZuwUrd`-6#ve-U+Eu8TmB3NW1|elfI&k$C|&X`0>uuHe_UDDGyYsO_oiJ^#E)0dd=b!gSoSr_P*K*o796mRAA<)p#-0p1i1U&uTpnSIA zTC7_lv@jbpWxv~~9CrVbBTHuzu_1}X!VZ0INvmf#(C0IUeO_}?YTng4qE>fNQFG(7 zr@OnF+fP*&74>!o2m6EGP^ddH=85&T5;@URzmz!eOnfwjH-uI%?}1DjRJLwRV@Sp`ohAHKNdH ze=5DPfk*VACnZ|W`Tfe)+g&6!HkEcPR{+7tEniRzDcl>9mWyV`z>lF-= z_-*JWXcB4n9Vn;KJ21Kf^ouY{V~g+su3x5|U&FLo5L~JzRSUhi2nXrHCAiKOmf(^W zQ=+tP1xnFupuQC--w}_mKnYt|fen$fYOdePT)1fNfMXPp`x8-sL{mkPkv`QntO}Z zm0>=0*W>H#K|NL@5SG)3>p-Q0n4n|rn8R{hc;x6r0DAyfZva2y-8jz+2_o;<1@=UXo>4OmN1Q_-Nkx??!S>|;Wd1i75@vH0CcqZ5f<{Fz4!=Mby`U0)$Tn_ z8s5V1H3gi)-AiEMZM=#5M)^f=@w{ETvV&PYlDAMy-OJq+iJnmRpEw)W5I4kiqzS~5 zz0cuP(gVDY2DYXr#X#L!G8;GW#2FJwp>89YrC)4d7R|~g4qdzVLc>776O7ndYc{DO Z)RITKh)zKEW*!+)Pvnv44x$_l{|jQ_h{FH? delta 1169 zcmYjQZA?>V6u#%Yw=Jc&9~3DKGQLGVEa9VI$-0D6=#U`_V@hOhE3 z`TXa)5R!!}O+1u|`}s`u@MhcVOFGfduOw7)9Ji@FdgcNYsLm_eWvNfK3Gj*3r)fmd zttwL$D(s5%M7s!DPN(1$MV|VL>$+tvY=!4-Q>r2beJ4E;ULgsnK>fBs3YvI=r>}`0 zB{%c=&)D^3AyK-LaS-%@fbV4I`+aWj+wb~H#O$^&#K{H0m(9OTqjKpwh~%W z3^vi0ac+8eOkb=dz!^E<(m4&MR{sBW!fBtw8g8osPP%nz2#5m2j?X8g>tio!#o7Km zF>h)tJXy2FOYX^U3GwCT(n|sqN`Fq7c7~Va@kL&emz+Dpae4d?KH-=*=Yl!FJF*vsW`l`y#qoXPZ*mFTJ7ge=ww z8y{k;K6VY-2t70pMWCi1&%+QkEI^dbEWky2=mw0dJ*oy(ql$ig7H+V)n{ZZ3J*$vU zyH=ryezt{5??D2aTZK4JJJ-?7=GGt`=`TM)iTVY@@A?8@raOQ<4GW}%)!c(9!XSHi zA0DKU1z4s7M$8toG-*uu7uL;8Hlb4^K4?#&DQWoCgcVWqW>a_fiG5vS$h(_8N<#yQ zcu`is`Kzup3WCw9)HVg zRkL^jnhAZY5EEm2u!d)~rMSk^^hz|NC6Sd@;vSy8QH|qBO;%Ln{gW{#R;l>umC^5M zb0MbFcU*YdVEudW%xL9m-1>7#sx{7jb)g*rS!x|V1UN?H-=Kxv@!+oAbg~z9ROiR5 zkuE%cBJzAzXK#>x zu%Hy9T1LGg|CGn!sBqO*?6tW(d+Tg=m&a~%R5@I>N_(}vwyN4)S6)}%&(iPWZ#yCh zBpQ2!4WLYH-($>HGC1)V*Ahjyx{L-l@U~c|E@i<@oWUI%$|*iCL&{<^7m`_^n}pot zjoY1N>pT$%izbkEpttX$ks1x;LM)Lq0H68HDX1eyAhFsoqUS=&1%%j|K$NYB8kDGr zg+wPzL`|a>(!@3_q?A}(`|FQ(?0W6h`qt(xc-YqohwE#pU?g3U91_~P6?QI-^lSbD DZUci@ diff --git a/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.cpp b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.cpp new file mode 100644 index 0000000000..02a8b08c70 --- /dev/null +++ b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.cpp @@ -0,0 +1,145 @@ +// ShutdownBOINCManager.cpp : Defines the entry point for the DLL application. +// + +#include "stdafx.h" + + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + return TRUE; +} + + +///////////////////////////////////////////////////////////////////// +// +// Function: LogError +// +// Description: This function writes to the MSI log file and displays +// the SetupError dialog box as appropriate. +// +///////////////////////////////////////////////////////////////////// +int LogError( + MSIHANDLE hInstall, // handle to the installation session + UINT msgType, // message type to send to Windows Installer + UINT pbStyle, // push button sstyle to use in message box + UINT iconStyle, // icon style to use in message box + int errNum, // number of error in Error table + TCHAR* ActionName, // name of the custom action causing error + TCHAR* ErrorDesc, // description of the error + int statuscode // the return value from an api + ) +{ + PMSIHANDLE hRec; // handle to a record object + TCHAR frmtString[4096]; // string to use in field 0 + + switch(msgType) + { + // Send informational message to the log file + case INSTALLMESSAGE_INFO: + // generate the format string for field 0 + _tcscpy(frmtString, _T("Custom Message : ")); + _tcscat(frmtString, _T("Action Name: [1] ")); + _tcscat(frmtString, _T("Description: [2] ")); + _tcscat(frmtString, _T("Status Code: [3] ")); + + hRec = MsiCreateRecord(3); + + MsiRecordSetString(hRec, 0, frmtString); + MsiRecordSetString(hRec, 1, ActionName); + MsiRecordSetString(hRec, 2, ErrorDesc); + MsiRecordSetInteger(hRec, 3, statuscode); + + // returns IDOK if successful + return (MsiProcessMessage(hInstall, INSTALLMESSAGE_INFO, + hRec)); + break; + + // Display a dialog and send error message to log file + case INSTALLMESSAGE_ERROR: + case INSTALLMESSAGE_WARNING: + case INSTALLMESSAGE_USER: + hRec = MsiCreateRecord(4); + + MsiRecordSetInteger(hRec, 1, errNum); + MsiRecordSetString(hRec, 2, ActionName); + MsiRecordSetString(hRec, 3, ErrorDesc); + MsiRecordSetInteger(hRec, 4, statuscode); + + // Return value to indicate which button is + // pushed on message box + return (MsiProcessMessage(hInstall, + INSTALLMESSAGE(msgType|pbStyle|iconStyle), hRec)); + break; + } + return 0; +} + + +///////////////////////////////////////////////////////////////////// +// +// Function: ShutdownBOINCManager +// +// Description: This custom action shuts down the BOINC Manager. +// +///////////////////////////////////////////////////////////////////// +UINT __stdcall ShutdownBOINCManager(MSIHANDLE hInstall) +{ + HWND hWndBOINCManagerSystray = NULL; + LRESULT lrReturnValue = NULL; + UINT uiLoopCounter = 0; + UINT uiReturn = -1; + + const UINT WM_TASKBARSHUTDOWN = ::RegisterWindowMessage(_T("TaskbarShutdown")); + + do + { + hWndBOINCManagerSystray = FindWindow( _T("wxTaskBarExWindowClass"), _T("BOINCManagerSystray") ); + if ( NULL != hWndBOINCManagerSystray ) + { + lrReturnValue = SendMessage( hWndBOINCManagerSystray, WM_TASKBARSHUTDOWN, NULL, NULL ); + if ( 0 != lrReturnValue ) + { + LogError( + hInstall, + INSTALLMESSAGE_ERROR, + NULL, + NULL, + NULL, + _T("ShutdownBOINCManager"), + _T("Setup was unable to shutdown the BOINC Manager Systray window."), + (int)lrReturnValue + ); + return ERROR_INSTALL_FAILURE; + } + Sleep(1000); + } + uiLoopCounter++; + } + while ( (NULL != hWndBOINCManagerSystray) && ( 20 >= uiLoopCounter ) ); + + if ( NULL != hWndBOINCManagerSystray ) + { + LogError( + hInstall, + INSTALLMESSAGE_ERROR, + NULL, + NULL, + NULL, + _T("ShutdownBOINCManager"), + _T("One or more BOINC Manager applications could not be closed, please close them and then rerun setup."), + uiLoopCounter + ); + return ERROR_INSTALL_FAILURE; + } + + // Give the manager a few seconds to shutdown. + Sleep(5000); + + return ERROR_SUCCESS; +} + + +const char *BOINC_RCSID_eeaf7c4c79 = "$Id$"; diff --git a/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.def b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.def new file mode 100644 index 0000000000..6f093ae78d --- /dev/null +++ b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.def @@ -0,0 +1,8 @@ +; +; Module definition file for the shutdown.dll +; + +LIBRARY shutdown + +EXPORTS + ShutdownBOINCManager PRIVATE diff --git a/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.sln b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.sln new file mode 100644 index 0000000000..34406d3794 --- /dev/null +++ b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.sln @@ -0,0 +1,21 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShutdownBOINCManager", "ShutdownBOINCManager.vcproj", "{49723CA5-DA05-43C0-93AB-6FD30D046919}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {49723CA5-DA05-43C0-93AB-6FD30D046919}.Debug.ActiveCfg = Debug|Win32 + {49723CA5-DA05-43C0-93AB-6FD30D046919}.Debug.Build.0 = Debug|Win32 + {49723CA5-DA05-43C0-93AB-6FD30D046919}.Release.ActiveCfg = Release|Win32 + {49723CA5-DA05-43C0-93AB-6FD30D046919}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.vcproj b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.vcproj new file mode 100644 index 0000000000..ddc3b9930f --- /dev/null +++ b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/ShutdownBOINCManager.vcproj @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/stdafx.cpp b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/stdafx.cpp new file mode 100644 index 0000000000..711b0c75d9 --- /dev/null +++ b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/stdafx.cpp @@ -0,0 +1,10 @@ +// stdafx.cpp : source file that includes just the standard includes +// NativeImage.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file + +const char *BOINC_RCSID_140925f16d = "$Id$"; diff --git a/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/stdafx.h b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/stdafx.h new file mode 100644 index 0000000000..b575180d53 --- /dev/null +++ b/win_build/installerv2/redist/Windows/src/ShutdownBOINCManager/stdafx.h @@ -0,0 +1,22 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +// Need to specify the smallest version of Windows Installer +// that supports file hashing. This is version 2.0. +#define _WIN32_MSI 200 + +// Exclude rarely-used stuff from Windows headers +#define WIN32_LEAN_AND_MEAN + + +// Windows Header Files: +#include +#include +#include +#include +#include +#include diff --git a/win_build/installerv2/redist/Windows/x86/shutdown.dll b/win_build/installerv2/redist/Windows/x86/shutdown.dll new file mode 100644 index 0000000000000000000000000000000000000000..954f832a04271c86da84ac3bfd1ed21b424fa351 GIT binary patch literal 45056 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 literal 0 HcmV?d00001