| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| 1 /** | 1 /** |
| 2 * \file close_application.cpp | 2 * \file close_application.cpp |
| 3 */ | 3 */ |
| 4 | 4 |
| 5 #include <algorithm> | 5 #include <algorithm> |
| 6 | 6 |
| 7 #include "session.h" | 7 #include "session.h" |
| 8 #include "property.h" | 8 #include "property.h" |
| 9 #include "database.h" | 9 #include "database.h" |
| 10 #include "process.h" | 10 #include "process.h" |
| 11 #include "interaction.h" | 11 #include "interaction.h" |
| 12 #include "custom-i18n.h" | 12 #include "custom-i18n.h" |
| 13 | 13 |
| 14 const wchar_t * ie_names[] = { L"IExplore.exe" } ; | 14 const wchar_t * browserNames[] = { L"IExplore.exe" } ; |
| 15 const wchar_t * engine_names[] = { L"AdblockPlusEngine.exe" } ; | 15 const wchar_t * engineNames[] = { L"AdblockPlusEngine.exe" } ; |
| 16 | 16 |
| 17 //------------------------------------------------------- | 17 //------------------------------------------------------- |
| 18 //------------------------------------------------------- | 18 //------------------------------------------------------- |
| 19 class IE_Closer | 19 class InternetExplorerCloser |
| 20 { | 20 { |
| 21 Process_Snapshot snapshot ; | 21 ProcessSnapshot snapshot ; |
| 22 | 22 |
| 23 Process_Closer ie_closer ; | 23 ProcessCloser browserCloser ; |
| 24 | 24 |
| 25 Process_Closer engine_closer ; | 25 ProcessCloser engineCloser ; |
| 26 | 26 |
| 27 public: | 27 public: |
| 28 IE_Closer() | 28 InternetExplorerCloser() |
| 29 : snapshot(), ie_closer( snapshot, ie_names), engine_closer( snapshot, engin e_names ) | 29 : snapshot(), browserCloser( snapshot, browserNames ), engineCloser( snapsho t, engineNames ) |
| 30 {} | 30 {} |
| 31 | 31 |
| 32 void refresh() | 32 void refresh() |
| 33 { | 33 { |
| 34 snapshot.refresh() ; | 34 snapshot.refresh() ; |
| 35 ie_closer.refresh() ; | 35 browserCloser.refresh() ; |
| 36 engine_closer.refresh() ; | 36 engineCloser.refresh() ; |
| 37 } | 37 } |
| 38 | 38 |
| 39 bool is_running() | 39 bool isRunning() |
|
Felix Dahlke
2014/10/15 02:46:57
Functions should start with an upper case letter.
Eric
2014/10/15 15:30:44
Missed that one, apparently.
| |
| 40 { | 40 { |
| 41 return ie_closer.is_running() || engine_closer.is_running() ; | 41 return browserCloser.isRunning() || engineCloser.isRunning() ; |
| 42 } | 42 } |
| 43 | 43 |
| 44 bool shut_down() | 44 bool shutDown() |
| 45 { | 45 { |
| 46 if ( ie_closer.is_running() && ! ie_closer.shut_down() ) | 46 if ( browserCloser.isRunning() && ! browserCloser.shutDown() ) |
| 47 { | 47 { |
| 48 // Assert IE is still running | 48 // Assert IE is still running |
| 49 // This is after we've tried to shut it down, so we fail | 49 // This is after we've tried to shut it down, so we fail |
| 50 return false ; | 50 return false ; |
| 51 } | 51 } |
| 52 if ( engine_closer.is_running() && ! engine_closer.shut_down() ) | 52 if ( engineCloser.isRunning() && ! engineCloser.shutDown() ) |
| 53 { | 53 { |
| 54 // Assert the engine is still running | 54 // Assert the engine is still running |
| 55 // This is after IE has shut down itself and after we've tried to shut dow n the engine. Whatever. | 55 // This is after IE has shut down itself and after we've tried to shut dow n the engine. Whatever. |
| 56 return false ; | 56 return false ; |
| 57 } | 57 } |
| 58 return true ; | 58 return true ; |
| 59 } | 59 } |
| 60 } ; | 60 } ; |
| 61 | 61 |
| 62 | 62 |
| 63 //------------------------------------------------------- | 63 //------------------------------------------------------- |
| 64 // abp_close_ie | 64 // AbpCloseIe |
| 65 //------------------------------------------------------- | 65 //------------------------------------------------------- |
| 66 /** | 66 /** |
| 67 * Exposed DLL entry point for custom action. | 67 * Exposed DLL entry point for custom action. |
| 68 * The function signature matches the calling convention used by Windows Install er. | 68 * The function signature matches the calling convention used by Windows Install er. |
| 69 * | 69 * |
| 70 * This function supports four policy stances with respect to a running IE proce ss. | 70 * This function supports four policy stances with respect to a running IE proce ss. |
| 71 * | 71 * |
| 72 * - Allow reboot. | 72 * - Allow reboot. |
| 73 * IE is running, so what? I'm willing to reboot after installation. | 73 * IE is running, so what? I'm willing to reboot after installation. |
| 74 * - Avoid reboot passively. | 74 * - Avoid reboot passively. |
| 75 * I don't want to affect any other running processes, but I don't want to reb oot. I'll abort the installation. | 75 * I don't want to affect any other running processes, but I don't want to reb oot. I'll abort the installation. |
| 76 * - Avoid reboot actively. | 76 * - Avoid reboot actively. |
| 77 * I want to shut down IE in order to avoid a reboot. | 77 * I want to shut down IE in order to avoid a reboot. |
| 78 * I'll do it manually when the time is right. | 78 * I'll do it manually when the time is right. |
| 79 * - Avoid reboot automatically. | 79 * - Avoid reboot automatically. |
| 80 * I want to shut down IE automatically in order to avoid a reboot. | 80 * I want to shut down IE automatically in order to avoid a reboot. |
| 81 * | 81 * |
| 82 * In a silent installation, the default stance is "allow reboot", which is to s ay, to act like most installers. | 82 * In a silent installation, the default stance is "allow reboot", which is to s ay, to act like most installers. |
| 83 * In an interactive installation, the stance is gathered from the user through dialog boxes. | 83 * In an interactive installation, the stance is gathered from the user through dialog boxes. |
| 84 * If the MSI property AVOIDREBOOT is set to one of the values NO, PASSIVE, ACTI VE, or AUTOMATIC, the policy is set accordingly. | 84 * If the MSI property AVOIDREBOOT is set to one of the values NO, PASSIVE, ACTI VE, or AUTOMATIC, the policy is set accordingly. |
| 85 * In a silent installation, this is the only way getting a stance other than th e default. | 85 * In a silent installation, this is the only way getting a stance other than th e default. |
| 86 * In an interactive installation, AVOIDREBOOT skips the dialogs. | 86 * In an interactive installation, AVOIDREBOOT skips the dialogs. |
| 87 * | 87 * |
| 88 * \param[in] session_handle | 88 * \param[in] sessionHandle |
| 89 * Windows installer session handle | 89 * Windows installer session handle |
| 90 * | 90 * |
| 91 * \return | 91 * \return |
| 92 * An integer interpreted as a custom action return value. | 92 * An integer interpreted as a custom action return value. |
| 93 * | 93 * |
| 94 * \post | 94 * \post |
| 95 * + The return value is one of the following: | 95 * + The return value is one of the following: |
| 96 * - ERROR_INSTALL_USEREXIT if the user cancelled installation. | 96 * - ERROR_INSTALL_USEREXIT if the user cancelled installation. |
| 97 * - ERROR_INSTALL_FAILURE if something unexpected happened, usually if the top level try-block caught an exception. | 97 * - ERROR_INSTALL_FAILURE if something unexpected happened, usually if the top level try-block caught an exception. |
| 98 * - ERROR_SUCCESS otherwise. | 98 * - ERROR_SUCCESS otherwise. |
| 99 * + The function performed at least one check that Internet Explorer was runn ing. | 99 * + The function performed at least one check that Internet Explorer was runn ing. |
| 100 * + If ERROR_SUCCESS, the MSI property RUNNINGBROWSER is set and has one of t he following values: | 100 * + If ERROR_SUCCESS, the MSI property RUNNINGBROWSER is set and has one of t he following values: |
| 101 * - 1 if Internet Explorer was running upon the last check. | 101 * - 1 if Internet Explorer was running upon the last check. |
| 102 * - 0 otherwise. | 102 * - 0 otherwise. |
| 103 * \post | 103 * \post |
| 104 * Note that this function cannot provide any assurance that Internet Explorer stays either stays running or stays not running. | 104 * Note that this function cannot provide any assurance that Internet Explorer stays either stays running or stays not running. |
| 105 * | 105 * |
| 106 * \sa | 106 * \sa |
| 107 * - MSDN [Custom Action Return Values](http://msdn.microsoft.com/en-us/librar y/aa368072%28v=vs.85%29.aspx) | 107 * - MSDN [Custom Action Return Values](http://msdn.microsoft.com/en-us/librar y/aa368072%28v=vs.85%29.aspx) |
| 108 */ | 108 */ |
| 109 extern "C" UINT __stdcall | 109 extern "C" UINT __stdcall |
| 110 abp_close_ie( MSIHANDLE session_handle ) | 110 AbpCloseIe( MSIHANDLE sessionHandle ) |
| 111 { | 111 { |
| 112 // Utility typedef to shorten the class name. | 112 // Utility typedef to shorten the class name. |
| 113 typedef Installer_Message_Box IMB ; | 113 typedef InstallerMessageBox IMB ; |
| 114 | 114 |
| 115 /* | 115 /* |
| 116 * Immediate_Session cannot throw, so it can go outside the try-block. | 116 * ImmediateSession cannot throw, so it can go outside the try-block. |
| 117 * It's needed in the catch-all block to write an error message to the log. | 117 * It's needed in the catch-all block to write an error message to the log. |
| 118 */ | 118 */ |
| 119 Immediate_Session session( session_handle, "abp_close_ie" ) ; | 119 ImmediateSession session( sessionHandle, "AbpCloseIe" ) ; |
| 120 | 120 |
| 121 // The body of an entry point function must have a catch-all. | 121 // The body of an entry point function must have a catch-all. |
| 122 try { | 122 try { |
| 123 | 123 |
| 124 // MSI property BROWSERRUNNING is one of the return values of this function. | 124 // MSI property BROWSERRUNNING is one of the return values of this function. |
| 125 Property browser_running( session, L"BROWSERRUNNING" ) ; | 125 Property browserRunning( session, L"BROWSERRUNNING" ) ; |
| 126 Property browser_closed( session, L"BROWSERCLOSED" ) ; | 126 Property browserClosed( session, L"BROWSERCLOSED" ) ; |
| 127 | 127 |
| 128 // Instantiation of Process_Closer takes a snapshot. | 128 // Instantiation of ProcessCloser takes a snapshot. |
| 129 IE_Closer iec ; | 129 InternetExplorerCloser iec ; |
| 130 | 130 |
| 131 /* | 131 /* |
| 132 * We take the short path through this function if neither IE nor engine is not running at the outset. | 132 * We take the short path through this function if neither IE nor engine is not running at the outset. |
| 133 */ | 133 */ |
| 134 if ( ! iec.is_running() ) | 134 if ( ! iec.isRunning() ) |
| 135 { | 135 { |
| 136 browser_running = L"0" ;» // The browser is not running. | 136 browserRunning = L"0" ;» // The browser is not running. |
| 137 browser_closed = L"0" ;» // We didn't close the browser (and we could n't have). | 137 browserClosed = L"0" ;» // We didn't close the browser (and we could n't have). |
| 138 session.log( "IE not running. No issue with reboot policy." ) ; | 138 session.log( "IE not running. No issue with reboot policy." ) ; |
| 139 return ERROR_SUCCESS ; | 139 return ERROR_SUCCESS ; |
| 140 } | 140 } |
| 141 | 141 |
| 142 /* | 142 /* |
| 143 * As a (potentially) user-driven function, a state machine manages control flow. | 143 * As a (potentially) user-driven function, a state machine manages control flow. |
| 144 * The states are organized around the policy stances. | 144 * The states are organized around the policy stances. |
| 145 */ | 145 */ |
| 146 enum Policy_State { | 146 enum PolicyState { |
| 147 // Non-terminal states | 147 // Non-terminal states |
| 148 not_known,» // We don't know the user's stance at all | 148 notKnown,» // We don't know the user's stance at all |
| 149 part_known,» // The user has indicated either ACTIVE or AUTOMATIC | 149 partKnown,» // The user has indicated either ACTIVE or AUTOMATIC |
| 150 active, // Actively avoid reboot | 150 active, // Actively avoid reboot |
| 151 automatic, // Automatically avoid reboot | 151 automatic, // Automatically avoid reboot |
| 152 // Terminal states | 152 // Terminal states |
| 153 success, | 153 success, |
| 154 abort, | 154 abort, |
| 155 // Aliases for what would ordinarily be non-terminal states. | 155 // Aliases for what would ordinarily be non-terminal states. |
| 156 // They're terminal because of implementation details. | 156 // They're terminal because of implementation details. |
| 157 allow = success, // Allow reboot. | 157 allow = success, // Allow reboot. |
| 158 passive = abort, // Passively avoid reboot, that is, don't try to close IE. | 158 passive = abort, // Passively avoid reboot, that is, don't try to close IE. |
| 159 }; | 159 }; |
| 160 Policy_State state ; | 160 PolicyState state ; |
| 161 | 161 |
| 162 /* | 162 /* |
| 163 * Use the AVOIDREBOOT property, if present, to set an initial state. | 163 * Use the AVOIDREBOOT property, if present, to set an initial state. |
| 164 */ | 164 */ |
| 165 std::wstring avoid_reboot = Property( session, L"AVOIDREBOOT" ) ; | 165 std::wstring avoidReboot = Property( session, L"AVOIDREBOOT" ) ; |
| 166 std::transform( avoid_reboot.begin(), avoid_reboot.end(), avoid_reboot.begin (), ::towupper ) ; | 166 std::transform( avoidReboot.begin(), avoidReboot.end(), avoidReboot.begin(), ::towupper ) ; |
| 167 if ( avoid_reboot == L"" ) | 167 if ( avoidReboot == L"" ) |
| 168 { | 168 { |
| 169 state = not_known ; | 169 state = notKnown ; |
| 170 } | 170 } |
| 171 else if ( avoid_reboot == L"NO" ) | 171 else if ( avoidReboot == L"NO" ) |
| 172 { | 172 { |
| 173 state = allow ; | 173 state = allow ; |
| 174 session.log( "Reboot allowed on command line." ) ; | 174 session.log( "Reboot allowed on command line." ) ; |
| 175 } | 175 } |
| 176 else if ( avoid_reboot == L"PASSIVE" ) | 176 else if ( avoidReboot == L"PASSIVE" ) |
| 177 { | 177 { |
| 178 state = passive ; | 178 state = passive ; |
| 179 session.log( "Reboot avoided on command line." ) ; | 179 session.log( "Reboot avoided on command line." ) ; |
| 180 } | 180 } |
| 181 else if ( avoid_reboot == L"ACTIVE" ) | 181 else if ( avoidReboot == L"ACTIVE" ) |
| 182 { | 182 { |
| 183 state = active ; | 183 state = active ; |
| 184 } | 184 } |
| 185 else if ( avoid_reboot == L"AUTOMATIC" ) | 185 else if ( avoidReboot == L"AUTOMATIC" ) |
| 186 { | 186 { |
| 187 state = automatic ; | 187 state = automatic ; |
| 188 } | 188 } |
| 189 else | 189 else |
| 190 { | 190 { |
| 191 // It's an error to specify an unrecognized value for AVOIDREBOOT. | 191 // It's an error to specify an unrecognized value for AVOIDREBOOT. |
| 192 throw std::runtime_error( "unrecognized value for AVOIDREBOOT" ) ; | 192 throw std::runtime_error( "unrecognized value for AVOIDREBOOT" ) ; |
| 193 } | 193 } |
| 194 | 194 |
| 195 /* | 195 /* |
| 196 * When running as an update (see Updater.cpp), this installer receives the command line option "/qb", | 196 * When running as an update (see Updater.cpp), this installer receives the command line option "/qb", |
| 197 * which sets the UI level to "Basic UI". | 197 * which sets the UI level to "Basic UI". |
| 198 * When running as an initial install, we cannot expect what command line op tions this installer receives. | 198 * When running as an initial install, we cannot expect what command line op tions this installer receives. |
| 199 */ | 199 */ |
| 200 /* | 200 /* |
| 201 * The UILevel property indicates whether we have the ability to put dialog boxes up. | 201 * The UILevel property indicates whether we have the ability to put dialog boxes up. |
| 202 * Levels 2 (silent) and 3 (basic) do not have this ability. | 202 * Levels 2 (silent) and 3 (basic) do not have this ability. |
| 203 * Levels 4 (reduced) and 5 (full) do. | 203 * Levels 4 (reduced) and 5 (full) do. |
| 204 * | 204 * |
| 205 * MSDN [UILevel property](http://msdn.microsoft.com/en-us/library/windows/d esktop/aa372096%28v=vs.85%29.aspx) | 205 * MSDN [UILevel property](http://msdn.microsoft.com/en-us/library/windows/d esktop/aa372096%28v=vs.85%29.aspx) |
| 206 */ | 206 */ |
| 207 std::wstring uilevel = Property( session, L"UILevel" ) ; | 207 std::wstring uilevel = Property( session, L"UILevel" ) ; |
| 208 bool interactive ; | 208 bool interactive ; |
| 209 if ( uilevel == L"5" || uilevel == L"4" ) | 209 if ( uilevel == L"5" || uilevel == L"4" ) |
| 210 { | 210 { |
| 211 interactive = true ; | 211 interactive = true ; |
| 212 // Assert state is one of { not_known, allow, passive, active, automatic } | 212 // Assert state is one of { notKnown, allow, passive, active, automatic } |
| 213 } | 213 } |
| 214 else if ( uilevel == L"3" || uilevel == L"2" ) | 214 else if ( uilevel == L"3" || uilevel == L"2" ) |
| 215 { | 215 { |
| 216 // Assert installer is running without user interaction. | 216 // Assert installer is running without user interaction. |
| 217 interactive = false ; | 217 interactive = false ; |
| 218 if ( state == not_known ) | 218 if ( state == notKnown ) |
| 219 { | 219 { |
| 220 // Assert AVOIDREBOOT was not specified | 220 // Assert AVOIDREBOOT was not specified |
| 221 /* | 221 /* |
| 222 * This is where we specify default behavior for non-interactive operati on. | 222 * This is where we specify default behavior for non-interactive operati on. |
| 223 * The choice of "allow" makes it act like other installers, which is to make no effort to avoid a reboot after installation. | 223 * The choice of "allow" makes it act like other installers, which is to make no effort to avoid a reboot after installation. |
| 224 */ | 224 */ |
| 225 state = allow ; | 225 state = allow ; |
| 226 session.log( "Reboot allowed by default in non-interactive session." ) ; | 226 session.log( "Reboot allowed by default in non-interactive session." ) ; |
| 227 } | 227 } |
| 228 else if ( state == active ) | 228 else if ( state == active ) |
| 229 { | 229 { |
| 230 throw std::runtime_error( "AVOIDREBOOT=ACTIVE in non-interative session is not consistent" ) ; | 230 throw std::runtime_error( "AVOIDREBOOT=ACTIVE in non-interative session is not consistent" ) ; |
| 231 } | 231 } |
| 232 // Assert state is one of { allow, passive, automatic } | 232 // Assert state is one of { allow, passive, automatic } |
| 233 } | 233 } |
| 234 else | 234 else |
| 235 { | 235 { |
| 236 throw std::runtime_error( "unrecognized value for UILevel" ) ; | 236 throw std::runtime_error( "unrecognized value for UILevel" ) ; |
| 237 } | 237 } |
| 238 | 238 |
| 239 /* | 239 /* |
| 240 * Now that preliminaries are over, we set up the accessors for UI text. | 240 * Now that preliminaries are over, we set up the accessors for UI text. |
| 241 * We only use the object 'message_text' for interactive sessions, but it's cheap to set up and a hassle to conditionalize. | 241 * We only use the object 'messageText' for interactive sessions, but it's c heap to set up and a hassle to conditionalize. |
| 242 * | 242 * |
| 243 * The key "close_ie" is the component name within the file "close_ie.wxi" t hat defines rows in the localization table. | 243 * The key "close_ie" is the component name within the file "close_ie.wxi" t hat defines rows in the localization table. |
| 244 * The identifiers for the message_text.text() function are defined within t hat file. | 244 * The identifiers for the messageText.text() function are defined within th at file. |
| 245 */ | 245 */ |
| 246 Installation_Database db( session ) ; | 246 InstallationDatabase db( session ) ; |
| 247 custom_message_text message_text( db, L"close_ie" ) ; | 247 CustomMessageText messageText( db, L"close_ie" ) ; |
| 248 | 248 |
| 249 /* | 249 /* |
| 250 * State machine: Loop through non-terminal states. | 250 * State machine: Loop through non-terminal states. |
| 251 * | 251 * |
| 252 * Loop invariant: IE was running at last check, that is, iec.is_running() w ould return true. | 252 * Loop invariant: IE was running at last check, that is, iec.isRunning() wo uld return true. |
| 253 */ | 253 */ |
| 254 while ( state <= automatic ) // "automatic" is the non-terminal sta te with the highest value | 254 while ( state <= automatic ) // "automatic" is the non-terminal sta te with the highest value |
| 255 { | 255 { |
| 256 switch ( state ) | 256 switch ( state ) |
| 257 { | 257 { |
| 258 case not_known: | 258 case notKnown: |
| 259 /* | 259 /* |
| 260 * Precondition: interactive session | 260 * Precondition: interactive session |
| 261 * | 261 * |
| 262 * Ask the user "Would you like to close IE and avoid reboot?" | 262 * Ask the user "Would you like to close IE and avoid reboot?" |
| 263 » * Yes -> Close IE somehow. Goto part_known. | 263 » * Yes -> Close IE somehow. Goto partKnown. |
| 264 * No -> Install with reboot. Goto allow. | 264 * No -> Install with reboot. Goto allow. |
| 265 * Cancel -> terminate installation. Goto abort. | 265 * Cancel -> terminate installation. Goto abort. |
| 266 */ | 266 */ |
| 267 { | 267 { |
| 268 » int x = session.write_message( IMB( message_text.text( L"dialog_unknow n" ), IMB::warning_box, IMB::yes_no_cancel, IMB::default_button_three ) ) ; | 268 » int x = session.WriteMessage( IMB( messageText.text( L"dialog_unknown" ), IMB::warningBox, IMB::yesNoCancel, IMB::defaultButtonThree ) ) ; |
| 269 switch ( x ) | 269 switch ( x ) |
| 270 { | 270 { |
| 271 case IDYES: | 271 case IDYES: |
| 272 » state = part_known ; | 272 » state = partKnown ; |
| 273 break ; | 273 break ; |
| 274 case IDNO: | 274 case IDNO: |
| 275 state = allow ; | 275 state = allow ; |
| 276 session.log( "User chose to allow reboot" ) ; | 276 session.log( "User chose to allow reboot" ) ; |
| 277 break ; | 277 break ; |
| 278 case IDCANCEL: | 278 case IDCANCEL: |
| 279 state = abort ; | 279 state = abort ; |
| 280 session.log( "User cancelled installation" ) ; | 280 session.log( "User cancelled installation" ) ; |
| 281 break ; | 281 break ; |
| 282 default: | 282 default: |
| 283 » throw unexpected_return_value_from_message_box() ; | 283 » throw UnexpectedReturnValueFromMessageBox() ; |
| 284 } | 284 } |
| 285 } | 285 } |
| 286 break ; | 286 break ; |
| 287 | 287 |
| 288 case part_known: | 288 case partKnown: |
| 289 /* | 289 /* |
| 290 * Precondition: interactive session | 290 * Precondition: interactive session |
| 291 * | 291 * |
| 292 * Ask the user "Would you like the installer to close IE for you?" | 292 * Ask the user "Would you like the installer to close IE for you?" |
| 293 * Yes -> Goto automatic | 293 * Yes -> Goto automatic |
| 294 * No -> Goto active | 294 * No -> Goto active |
| 295 » * Cancel -> Goto not_known | 295 » * Cancel -> Goto notKnown |
| 296 */ | 296 */ |
| 297 { | 297 { |
| 298 » int x = session.write_message( IMB( message_text.text( L"dialog_part_k nown" ), IMB::warning_box, IMB::yes_no_cancel, IMB::default_button_three ) ) ; | 298 » int x = session.WriteMessage( IMB( messageText.text( L"dialog_part_kno wn" ), IMB::warningBox, IMB::yesNoCancel, IMB::defaultButtonThree ) ) ; |
| 299 switch ( x ) | 299 switch ( x ) |
| 300 { | 300 { |
| 301 case IDYES: | 301 case IDYES: |
| 302 state = automatic ; | 302 state = automatic ; |
| 303 break ; | 303 break ; |
| 304 case IDNO: | 304 case IDNO: |
| 305 state = active ; | 305 state = active ; |
| 306 break ; | 306 break ; |
| 307 case IDCANCEL: | 307 case IDCANCEL: |
| 308 » state = not_known ; | 308 » state = notKnown ; |
| 309 break ; | 309 break ; |
| 310 default: | 310 default: |
| 311 » throw unexpected_return_value_from_message_box() ; | 311 » throw UnexpectedReturnValueFromMessageBox() ; |
| 312 } | 312 } |
| 313 } | 313 } |
| 314 break ; | 314 break ; |
| 315 | 315 |
| 316 case active: | 316 case active: |
| 317 /* | 317 /* |
| 318 * Precondition: interactive session | 318 * Precondition: interactive session |
| 319 * | 319 * |
| 320 * IE is no longer running -> Goto success | 320 * IE is no longer running -> Goto success |
| 321 * IE is still running -> | 321 * IE is still running -> |
| 322 * Ask the user to close IE manually | 322 * Ask the user to close IE manually |
| 323 * OK -> re-enter this state | 323 * OK -> re-enter this state |
| 324 » * Cancel -> Goto not_known | 324 » * Cancel -> Goto notKnown |
| 325 */ | 325 */ |
| 326 { | 326 { |
| 327 » int x = session.write_message( IMB( message_text.text( L"dialog_active _retry" ), IMB::warning_box, IMB::ok_cancel, IMB::default_button_one ) ) ; | 327 » int x = session.WriteMessage( IMB( messageText.text( L"dialog_active_r etry" ), IMB::warningBox, IMB::okCancel, IMB::defaultButtonOne ) ) ; |
| 328 switch ( x ) | 328 switch ( x ) |
| 329 { | 329 { |
| 330 case IDOK: | 330 case IDOK: |
| 331 /* | 331 /* |
| 332 * Refresh our knowledge of whether IE is running. | 332 * Refresh our knowledge of whether IE is running. |
| 333 * If it is, we display the dialog again. The state doesn't change, so we just iterate again. | 333 * If it is, we display the dialog again. The state doesn't change, so we just iterate again. |
| 334 * If it's not, then the user has closed IE and we're done. | 334 * If it's not, then the user has closed IE and we're done. |
| 335 */ | 335 */ |
| 336 iec.refresh() ; | 336 iec.refresh() ; |
| 337 » if ( ! iec.is_running() ) | 337 » if ( ! iec.isRunning() ) |
| 338 { | 338 { |
| 339 state = success ; | 339 state = success ; |
| 340 session.log( "User shut down IE manually." ) ; | 340 session.log( "User shut down IE manually." ) ; |
| 341 } | 341 } |
| 342 break ; | 342 break ; |
| 343 case IDCANCEL: | 343 case IDCANCEL: |
| 344 » state = not_known ; | 344 » state = notKnown ; |
| 345 break ; | 345 break ; |
| 346 default: | 346 default: |
| 347 » throw unexpected_return_value_from_message_box() ; | 347 » throw UnexpectedReturnValueFromMessageBox() ; |
| 348 } | 348 } |
| 349 } | 349 } |
| 350 break ; | 350 break ; |
| 351 | 351 |
| 352 case automatic: | 352 case automatic: |
| 353 /* | 353 /* |
| 354 * Close all known IE instances. | 354 * Close all known IE instances. |
| 355 * Unlike other cases, this state starts with an action and not a user q uery. | 355 * Unlike other cases, this state starts with an action and not a user q uery. |
| 356 * We first shut down IE, or at least attempt to. | 356 * We first shut down IE, or at least attempt to. |
| 357 * | 357 * |
| 358 * Succeeded -> Goto success | 358 * Succeeded -> Goto success |
| 359 * Failed && interactive -> | 359 * Failed && interactive -> |
| 360 * Ask user if they would like to try again | 360 * Ask user if they would like to try again |
| 361 * Retry -> re-enter this state | 361 * Retry -> re-enter this state |
| 362 » * Cancel -> Goto not_known | 362 » * Cancel -> Goto notKnown |
| 363 * Failed && not interactive -> Goto abort | 363 * Failed && not interactive -> Goto abort |
| 364 */ | 364 */ |
| 365 { | 365 { |
| 366 » bool IE_was_closed = iec.shut_down() ; | 366 » bool ieWasClosed = iec.shutDown() ; |
| 367 » if ( iec.is_running() ) | 367 » if ( iec.isRunning() ) |
| 368 { | 368 { |
| 369 session.log( "Attempt to shut down IE automatically failed." ) ; | 369 session.log( "Attempt to shut down IE automatically failed." ) ; |
| 370 if ( interactive ) | 370 if ( interactive ) |
| 371 { | 371 { |
| 372 // Assert Interactive session and IE did not shut down. | 372 // Assert Interactive session and IE did not shut down. |
| 373 » int x = session.write_message( IMB( message_text.text( L"dialog_au tomatic_retry" ), IMB::warning_box, IMB::retry_cancel, IMB::default_button_one ) ) ; | 373 » int x = session.WriteMessage( IMB( messageText.text( L"dialog_auto matic_retry" ), IMB::warningBox, IMB::retryCancel, IMB::defaultButtonOne ) ) ; |
| 374 switch ( x ) | 374 switch ( x ) |
| 375 { | 375 { |
| 376 case IDRETRY: | 376 case IDRETRY: |
| 377 // Don't change the state. Iterate again. | 377 // Don't change the state. Iterate again. |
| 378 break ; | 378 break ; |
| 379 case IDCANCEL: | 379 case IDCANCEL: |
| 380 » » state = not_known ; | 380 » » state = notKnown ; |
| 381 break ; | 381 break ; |
| 382 default: | 382 default: |
| 383 » » throw unexpected_return_value_from_message_box() ; | 383 » » throw UnexpectedReturnValueFromMessageBox() ; |
| 384 } | 384 } |
| 385 } | 385 } |
| 386 else | 386 else |
| 387 { | 387 { |
| 388 // Assert Non-interactive session and IE did not shut down. | 388 // Assert Non-interactive session and IE did not shut down. |
| 389 state = abort ; | 389 state = abort ; |
| 390 session.log( "Failed to shut down IE automatically." ) ; | 390 session.log( "Failed to shut down IE automatically." ) ; |
| 391 } | 391 } |
| 392 } | 392 } |
| 393 else | 393 else |
| 394 { | 394 { |
| 395 » // Assert IE is not running, so shut_down() succeeded. | 395 » // Assert IE is not running, so shutDown() succeeded. |
| 396 state = success ; | 396 state = success ; |
| 397 session.log( "Automatically shut down IE." ) ; | 397 session.log( "Automatically shut down IE." ) ; |
| 398 } | 398 } |
| 399 } | 399 } |
| 400 break; | 400 break; |
| 401 } | 401 } |
| 402 } | 402 } |
| 403 /* | 403 /* |
| 404 * State machine: Actions for terminal states. | 404 * State machine: Actions for terminal states. |
| 405 */ | 405 */ |
| 406 switch ( state ) | 406 switch ( state ) |
| 407 { | 407 { |
| 408 case success: | 408 case success: |
| 409 » if ( iec.is_running() ) | 409 » if ( iec.isRunning() ) |
| 410 { | 410 { |
| 411 » browser_running = L"1" ; | 411 » browserRunning = L"1" ; |
| 412 » browser_closed = L"0" ; | 412 » browserClosed = L"0" ; |
| 413 } | 413 } |
| 414 else | 414 else |
| 415 { | 415 { |
| 416 » browser_running = L"0" ; | 416 » browserRunning = L"0" ; |
| 417 » browser_closed = L"1" ; | 417 » browserClosed = L"1" ; |
| 418 } | 418 } |
| 419 return ERROR_SUCCESS ; | 419 return ERROR_SUCCESS ; |
| 420 break; | 420 break; |
| 421 case abort: | 421 case abort: |
| 422 return ERROR_INSTALL_USEREXIT ; | 422 return ERROR_INSTALL_USEREXIT ; |
| 423 break; | 423 break; |
| 424 } | 424 } |
| 425 } | 425 } |
| 426 catch( std::exception & e ) | 426 catch( std::exception & e ) |
| 427 { | 427 { |
| 428 session.log_noexcept( "terminated by exception: " + std::string( e.what() ) ) ; | 428 session.LogNoexcept( "terminated by exception: " + std::string( e.what() ) ) ; |
| 429 return ERROR_INSTALL_FAILURE ; | 429 return ERROR_INSTALL_FAILURE ; |
| 430 } | 430 } |
| 431 catch( ... ) | 431 catch( ... ) |
| 432 { | 432 { |
| 433 session.log_noexcept( "terminated by unknown exception" ) ; | 433 session.LogNoexcept( "terminated by unknown exception" ) ; |
| 434 return ERROR_INSTALL_FAILURE ; | 434 return ERROR_INSTALL_FAILURE ; |
| 435 } | 435 } |
| 436 // Should be unreachable. | 436 // Should be unreachable. |
| 437 return ERROR_INSTALL_FAILURE ; | 437 return ERROR_INSTALL_FAILURE ; |
| 438 } | 438 } |
| 439 | |
| 440 /* | |
| 441 * EnumWindows system call: http://msdn.microsoft.com/en-us/library/windows/desk top/ms633497%28v=vs.85%29.aspx | |
| 442 */ | |
| 443 /** | |
| 444 * | |
| 445 * Callback function for EnumWindows. | |
| 446 */ | |
| 447 BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) | |
| 448 { | |
| 449 return TRUE ; | |
| 450 } | |
| 451 | |
| 452 /** | |
| 453 * Windows_List | |
| 454 */ | |
| 455 class Window_List { | |
| 456 public: | |
| 457 void enumerate_top_level(); | |
| 458 }; | |
| OLD | NEW |