| 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 * browserNames[] = { L"IExplore.exe" } ; | 14 const wchar_t* browserNames[] = {L"IExplore.exe"}; |
| 15 const wchar_t * engineNames[] = { L"AdblockPlusEngine.exe" } ; | 15 const wchar_t* engineNames[] = {L"AdblockPlusEngine.exe"}; |
| 16 | 16 |
| 17 //------------------------------------------------------- | 17 //------------------------------------------------------- |
| 18 //------------------------------------------------------- | 18 //------------------------------------------------------- |
| 19 class InternetExplorerCloser | 19 class InternetExplorerCloser |
| 20 { | 20 { |
| 21 ProcessSnapshot snapshot ; | 21 ProcessSnapshot snapshot; |
| 22 | 22 |
| 23 ProcessCloser browserCloser ; | 23 ProcessCloser browserCloser; |
| 24 | 24 |
| 25 ProcessCloser engineCloser ; | 25 ProcessCloser engineCloser; |
| 26 | 26 |
| 27 public: | 27 public: |
| 28 InternetExplorerCloser() | 28 InternetExplorerCloser() |
| 29 : snapshot(), browserCloser( snapshot, browserNames ), engineCloser( snapsho
t, engineNames ) | 29 : snapshot(), browserCloser(snapshot, browserNames), engineCloser(snapshot,
engineNames) |
| 30 {} | 30 {} |
| 31 | 31 |
| 32 void Refresh() | 32 void Refresh() |
| 33 { | 33 { |
| 34 snapshot.Refresh() ; | 34 snapshot.Refresh(); |
| 35 browserCloser.Refresh() ; | 35 browserCloser.Refresh(); |
| 36 engineCloser.Refresh() ; | 36 engineCloser.Refresh(); |
| 37 } | 37 } |
| 38 | 38 |
| 39 bool IsRunning() | 39 bool IsRunning() |
| 40 { | 40 { |
| 41 return browserCloser.IsRunning() || engineCloser.IsRunning() ; | 41 return browserCloser.IsRunning() || engineCloser.IsRunning(); |
| 42 } | 42 } |
| 43 | 43 |
| 44 bool ShutDown() | 44 bool ShutDown() |
| 45 { | 45 { |
| 46 if ( browserCloser.IsRunning() && ! browserCloser.ShutDown() ) | 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 ( engineCloser.IsRunning() && ! engineCloser.ShutDown() ) | 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 | |
| 62 | 61 |
| 63 //------------------------------------------------------- | 62 //------------------------------------------------------- |
| 64 // AbpCloseIe | 63 // AbpCloseIe |
| 65 //------------------------------------------------------- | 64 //------------------------------------------------------- |
| 66 /** | 65 /** |
| 67 * Exposed DLL entry point for custom action. | 66 * Exposed DLL entry point for custom action. |
| 68 * The function signature matches the calling convention used by Windows Install
er. | 67 * The function signature matches the calling convention used by Windows Install
er. |
| 69 * | 68 * |
| 70 * This function supports four policy stances with respect to a running IE proce
ss. | 69 * This function supports four policy stances with respect to a running IE proce
ss. |
| 71 * | 70 * |
| (...skipping 27 matching lines...) Expand all Loading... |
| 99 * + The function performed at least one check that Internet Explorer was runn
ing. | 98 * + 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: | 99 * + 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. | 100 * - 1 if Internet Explorer was running upon the last check. |
| 102 * - 0 otherwise. | 101 * - 0 otherwise. |
| 103 * \post | 102 * \post |
| 104 * Note that this function cannot provide any assurance that Internet Explorer
stays either stays running or stays not running. | 103 * Note that this function cannot provide any assurance that Internet Explorer
stays either stays running or stays not running. |
| 105 * | 104 * |
| 106 * \sa | 105 * \sa |
| 107 * - MSDN [Custom Action Return Values](http://msdn.microsoft.com/en-us/librar
y/aa368072%28v=vs.85%29.aspx) | 106 * - MSDN [Custom Action Return Values](http://msdn.microsoft.com/en-us/librar
y/aa368072%28v=vs.85%29.aspx) |
| 108 */ | 107 */ |
| 109 extern "C" UINT __stdcall | 108 extern "C" UINT __stdcall AbpCloseIe(MSIHANDLE sessionHandle) |
| 110 AbpCloseIe( MSIHANDLE sessionHandle ) | |
| 111 { | 109 { |
| 112 // Utility typedef to shorten the class name. | 110 // Utility typedef to shorten the class name. |
| 113 typedef InstallerMessageBox IMB ; | 111 typedef InstallerMessageBox IMB; |
| 114 | 112 |
| 115 /* | 113 /* |
| 116 * ImmediateSession cannot throw, so it can go outside the try-block. | 114 * 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. | 115 * It's needed in the catch-all block to write an error message to the log. |
| 118 */ | 116 */ |
| 119 ImmediateSession session( sessionHandle, "AbpCloseIe" ) ; | 117 ImmediateSession session(sessionHandle, "AbpCloseIe"); |
| 120 | 118 |
| 121 // The body of an entry point function must have a catch-all. | 119 // The body of an entry point function must have a catch-all. |
| 122 try { | 120 try |
| 123 | 121 { |
| 124 // MSI property BROWSERRUNNING is one of the return values of this function. | 122 // MSI property BROWSERRUNNING is one of the return values of this function. |
| 125 Property browserRunning( session, L"BROWSERRUNNING" ) ; | 123 Property browserRunning(session, L"BROWSERRUNNING"); |
| 126 Property browserClosed( session, L"BROWSERCLOSED" ) ; | 124 Property browserClosed(session, L"BROWSERCLOSED"); |
| 127 | 125 |
| 128 // Instantiation of ProcessCloser takes a snapshot. | 126 // Instantiation of ProcessCloser takes a snapshot. |
| 129 InternetExplorerCloser iec ; | 127 InternetExplorerCloser iec; |
| 130 | 128 |
| 131 /* | 129 /* |
| 132 * We take the short path through this function if neither IE nor engine is
not running at the outset. | 130 * We take the short path through this function if neither IE nor engine is
not running at the outset. |
| 133 */ | 131 */ |
| 134 if ( ! iec.IsRunning() ) | 132 if (!iec.IsRunning()) |
| 135 { | 133 { |
| 136 browserRunning = L"0" ;» // The browser is not running. | 134 browserRunning = L"0"; // The browser is not running. |
| 137 browserClosed = L"0" ;» // We didn't close the browser (and we could
n't have). | 135 browserClosed = L"0"; // We didn't close the browser (and we couldn't hav
e). |
| 138 session.Log( "IE not running. No issue with reboot policy." ) ; | 136 session.Log("IE not running. No issue with reboot policy."); |
| 139 return ERROR_SUCCESS ; | 137 return ERROR_SUCCESS; |
| 140 } | 138 } |
| 141 | 139 |
| 142 /* | 140 /* |
| 143 * As a (potentially) user-driven function, a state machine manages control
flow. | 141 * As a (potentially) user-driven function, a state machine manages control
flow. |
| 144 * The states are organized around the policy stances. | 142 * The states are organized around the policy stances. |
| 145 */ | 143 */ |
| 146 enum PolicyState { | 144 enum PolicyState |
| 145 { |
| 147 // Non-terminal states | 146 // Non-terminal states |
| 148 notKnown,» // We don't know the user's stance at all | 147 notKnown, // We don't know the user's stance at all |
| 149 partKnown,» // The user has indicated either ACTIVE or AUTOMATIC | 148 partKnown, // The user has indicated either ACTIVE or AUTOMATIC |
| 150 active,» » // Actively avoid reboot | 149 active, // Actively avoid reboot |
| 151 automatic, // Automatically avoid reboot | 150 automatic, // Automatically avoid reboot |
| 152 // Terminal states | 151 // Terminal states |
| 153 success, | 152 success, |
| 154 abort, | 153 abort, |
| 155 // Aliases for what would ordinarily be non-terminal states. | 154 // Aliases for what would ordinarily be non-terminal states. |
| 156 // They're terminal because of implementation details. | 155 // They're terminal because of implementation details. |
| 157 allow = success,» // Allow reboot. | 156 allow = success, // Allow reboot. |
| 158 passive = abort,» // Passively avoid reboot, that is, don't try to close
IE. | 157 passive = abort, // Passively avoid reboot, that is, don't try to close IE
. |
| 159 }; | 158 }; |
| 160 PolicyState state ; | 159 PolicyState state; |
| 161 | 160 |
| 162 /* | 161 /* |
| 163 * Use the AVOIDREBOOT property, if present, to set an initial state. | 162 * Use the AVOIDREBOOT property, if present, to set an initial state. |
| 164 */ | 163 */ |
| 165 std::wstring avoidReboot = Property( session, L"AVOIDREBOOT" ) ; | 164 std::wstring avoidReboot = Property(session, L"AVOIDREBOOT"); |
| 166 std::transform( avoidReboot.begin(), avoidReboot.end(), avoidReboot.begin(),
::towupper ) ; | 165 std::transform(avoidReboot.begin(), avoidReboot.end(), avoidReboot.begin(),
::towupper); |
| 167 if ( avoidReboot == L"" ) | 166 if (avoidReboot == L"") |
| 168 { | 167 { |
| 169 state = notKnown ; | 168 state = notKnown; |
| 170 } | 169 } |
| 171 else if ( avoidReboot == L"NO" ) | 170 else if (avoidReboot == L"NO") |
| 172 { | 171 { |
| 173 state = allow ; | 172 state = allow; |
| 174 session.Log( "Reboot allowed on command line." ) ; | 173 session.Log("Reboot allowed on command line."); |
| 175 } | 174 } |
| 176 else if ( avoidReboot == L"PASSIVE" ) | 175 else if (avoidReboot == L"PASSIVE") |
| 177 { | 176 { |
| 178 state = passive ; | 177 state = passive; |
| 179 session.Log( "Reboot avoided on command line." ) ; | 178 session.Log("Reboot avoided on command line."); |
| 180 } | 179 } |
| 181 else if ( avoidReboot == L"ACTIVE" ) | 180 else if (avoidReboot == L"ACTIVE") |
| 182 { | 181 { |
| 183 state = active ; | 182 state = active; |
| 184 } | 183 } |
| 185 else if ( avoidReboot == L"AUTOMATIC" ) | 184 else if (avoidReboot == L"AUTOMATIC") |
| 186 { | 185 { |
| 187 state = automatic ; | 186 state = automatic; |
| 188 } | 187 } |
| 189 else | 188 else |
| 190 { | 189 { |
| 191 // It's an error to specify an unrecognized value for AVOIDREBOOT. | 190 // It's an error to specify an unrecognized value for AVOIDREBOOT. |
| 192 throw std::runtime_error( "unrecognized value for AVOIDREBOOT" ) ; | 191 throw std::runtime_error("unrecognized value for AVOIDREBOOT"); |
| 193 } | 192 } |
| 194 | 193 |
| 195 /* | 194 /* |
| 196 * When running as an update (see Updater.cpp), this installer receives the
command line option "/qb", | 195 * 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". | 196 * 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. | 197 * When running as an initial install, we cannot expect what command line op
tions this installer receives. |
| 199 */ | 198 */ |
| 200 /* | 199 /* |
| 201 * The UILevel property indicates whether we have the ability to put dialog
boxes up. | 200 * 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. | 201 * Levels 2 (silent) and 3 (basic) do not have this ability. |
| 203 * Levels 4 (reduced) and 5 (full) do. | 202 * Levels 4 (reduced) and 5 (full) do. |
| 204 * | 203 * |
| 205 * MSDN [UILevel property](http://msdn.microsoft.com/en-us/library/windows/d
esktop/aa372096%28v=vs.85%29.aspx) | 204 * MSDN [UILevel property](http://msdn.microsoft.com/en-us/library/windows/d
esktop/aa372096%28v=vs.85%29.aspx) |
| 206 */ | 205 */ |
| 207 std::wstring uilevel = Property( session, L"UILevel" ) ; | 206 std::wstring uilevel = Property(session, L"UILevel"); |
| 208 bool interactive ; | 207 bool interactive; |
| 209 if ( uilevel == L"5" || uilevel == L"4" ) | 208 if (uilevel == L"5" || uilevel == L"4") |
| 210 { | 209 { |
| 211 interactive = true ; | 210 interactive = true; |
| 212 // Assert state is one of { notKnown, allow, passive, active, automatic } | 211 // Assert state is one of { notKnown, allow, passive, active, automatic } |
| 213 } | 212 } |
| 214 else if ( uilevel == L"3" || uilevel == L"2" ) | 213 else if (uilevel == L"3" || uilevel == L"2") |
| 215 { | 214 { |
| 216 // Assert installer is running without user interaction. | 215 // Assert installer is running without user interaction. |
| 217 interactive = false ; | 216 interactive = false; |
| 218 if ( state == notKnown ) | 217 if (state == notKnown) |
| 219 { | 218 { |
| 220 » // Assert AVOIDREBOOT was not specified | 219 // Assert AVOIDREBOOT was not specified |
| 221 » /* | 220 /* |
| 222 » * This is where we specify default behavior for non-interactive operati
on. | 221 * 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. | 222 * The choice of "allow" makes it act like other installers, which is to
make no effort to avoid a reboot after installation. |
| 224 » */ | 223 */ |
| 225 » state = allow ; | 224 state = allow; |
| 226 » session.Log( "Reboot allowed by default in non-interactive session." ) ; | 225 session.Log("Reboot allowed by default in non-interactive session."); |
| 227 } | 226 } |
| 228 else if ( state == active ) | 227 else if (state == active) |
| 229 { | 228 { |
| 230 » throw std::runtime_error( "AVOIDREBOOT=ACTIVE in non-interative session
is not consistent" ) ; | 229 throw std::runtime_error("AVOIDREBOOT=ACTIVE in non-interative session i
s not consistent"); |
| 231 } | 230 } |
| 232 // Assert state is one of { allow, passive, automatic } | 231 // Assert state is one of { allow, passive, automatic } |
| 233 } | 232 } |
| 234 else | 233 else |
| 235 { | 234 { |
| 236 throw std::runtime_error( "unrecognized value for UILevel" ) ; | 235 throw std::runtime_error("unrecognized value for UILevel"); |
| 237 } | 236 } |
| 238 | 237 |
| 239 /* | 238 /* |
| 240 * Now that preliminaries are over, we set up the accessors for UI text. | 239 * Now that preliminaries are over, we set up the accessors for UI text. |
| 241 * We only use the object 'messageText' for interactive sessions, but it's c
heap to set up and a hassle to conditionalize. | 240 * We only use the object 'messageText' for interactive sessions, but it's c
heap to set up and a hassle to conditionalize. |
| 242 * | 241 * |
| 243 * The key "close_ie" is the component name within the file "close_ie.wxi" t
hat defines rows in the localization table. | 242 * 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 messageText.text() function are defined within th
at file. | 243 * The identifiers for the messageText.text() function are defined within th
at file. |
| 245 */ | 244 */ |
| 246 InstallationDatabase db( session ) ; | 245 InstallationDatabase db(session); |
| 247 CustomMessageText messageText( db, L"close_ie" ) ; | 246 CustomMessageText messageText(db, L"close_ie"); |
| 248 | 247 |
| 249 /* | 248 /* |
| 250 * State machine: Loop through non-terminal states. | 249 * State machine: Loop through non-terminal states. |
| 251 * | 250 * |
| 252 * Loop invariant: IE was running at last check, that is, iec.IsRunning() wo
uld return true. | 251 * Loop invariant: IE was running at last check, that is, iec.IsRunning() wo
uld return true. |
| 253 */ | 252 */ |
| 254 while ( state <= automatic )» // "automatic" is the non-terminal sta
te with the highest value | 253 while (state <= automatic) // "automatic" is the non-terminal state with the
highest value |
| 255 { | 254 { |
| 256 switch ( state ) | 255 switch (state) |
| 257 { | 256 { |
| 258 case notKnown: | 257 case notKnown: |
| 259 » /* | 258 /* |
| 260 » * Precondition: interactive session | 259 * Precondition: interactive session |
| 261 » * | 260 * |
| 262 » * Ask the user "Would you like to close IE and avoid reboot?" | 261 * Ask the user "Would you like to close IE and avoid reboot?" |
| 263 » * Yes -> Close IE somehow. Goto partKnown. | 262 * Yes -> Close IE somehow. Goto partKnown. |
| 264 » * No -> Install with reboot. Goto allow. | 263 * No -> Install with reboot. Goto allow. |
| 265 » * Cancel -> terminate installation. Goto abort. | 264 * Cancel -> terminate installation. Goto abort. |
| 266 » */ | 265 */ |
| 267 { | 266 { |
| 268 int x = session.WriteMessage(IMB( | 267 int x = session.WriteMessage(IMB( |
| 269 messageText.Text(L"dialog_unknown"), | 268 messageText.Text(L"dialog_unknown"), |
| 270 IMB::Box::warning, IMB::ButtonSet::yesNoCancel, IMB::DefaultButton::
three | 269 IMB::Box::warning, IMB::ButtonSet::yesNoCancel, IMB::DefaultButton::
three)); |
| 271 )) ; | 270 switch (x) |
| 272 » switch ( x ) | 271 { |
| 273 » { | 272 case IDYES: |
| 274 » case IDYES: | 273 state = partKnown; |
| 275 » state = partKnown ; | 274 break; |
| 276 » break ; | 275 case IDNO: |
| 277 » case IDNO: | 276 state = allow; |
| 278 » state = allow ; | 277 session.Log("User chose to allow reboot"); |
| 279 » session.Log( "User chose to allow reboot" ) ; | 278 break; |
| 280 » break ; | 279 case IDCANCEL: |
| 281 » case IDCANCEL: | 280 state = abort; |
| 282 » state = abort ; | 281 session.Log("User cancelled installation"); |
| 283 » session.Log( "User cancelled installation" ) ; | 282 break; |
| 284 » break ; | 283 default: |
| 285 » default: | 284 throw UnexpectedReturnValueFromMessageBox(); |
| 286 » throw UnexpectedReturnValueFromMessageBox() ; | 285 } |
| 287 » } | 286 } |
| 288 » } | 287 break; |
| 289 » break ; | |
| 290 | 288 |
| 291 case partKnown: | 289 case partKnown: |
| 292 » /* | 290 /* |
| 293 » * Precondition: interactive session | 291 * Precondition: interactive session |
| 294 » * | 292 * |
| 295 » * Ask the user "Would you like the installer to close IE for you?" | 293 * Ask the user "Would you like the installer to close IE for you?" |
| 296 » * Yes -> Goto automatic | 294 * Yes -> Goto automatic |
| 297 » * No -> Goto active | 295 * No -> Goto active |
| 298 » * Cancel -> Goto notKnown | 296 * Cancel -> Goto notKnown |
| 299 » */ | 297 */ |
| 300 » { | 298 { |
| 301 » int x = session.WriteMessage(IMB( | 299 int x = session.WriteMessage(IMB( |
| 302 messageText.Text(L"dialog_part_known"), | 300 messageText.Text(L"dialog_part_known"), |
| 303 IMB::Box::warning, IMB::ButtonSet::yesNoCancel, IMB::DefaultButton::
three | 301 IMB::Box::warning, IMB::ButtonSet::yesNoCancel, IMB::DefaultButton::
three)); |
| 304 )) ; | 302 switch (x) |
| 305 » switch ( x ) | 303 { |
| 306 » { | 304 case IDYES: |
| 307 » case IDYES: | 305 state = automatic; |
| 308 » state = automatic ; | 306 break; |
| 309 » break ; | 307 case IDNO: |
| 310 » case IDNO: | 308 state = active; |
| 311 » state = active ; | 309 break; |
| 312 » break ; | 310 case IDCANCEL: |
| 313 » case IDCANCEL: | 311 state = notKnown; |
| 314 » state = notKnown ; | 312 break; |
| 315 » break ; | 313 default: |
| 316 » default: | 314 throw UnexpectedReturnValueFromMessageBox(); |
| 317 » throw UnexpectedReturnValueFromMessageBox() ; | 315 } |
| 318 » } | 316 } |
| 319 » } | 317 break; |
| 320 » break ; | |
| 321 | 318 |
| 322 case active: | 319 case active: |
| 323 » /* | 320 /* |
| 324 » * Precondition: interactive session | 321 * Precondition: interactive session |
| 325 » * | 322 * |
| 326 » * IE is no longer running -> Goto success | 323 * IE is no longer running -> Goto success |
| 327 » * IE is still running -> | 324 * IE is still running -> |
| 328 » * Ask the user to close IE manually | 325 * Ask the user to close IE manually |
| 329 » * OK -> re-enter this state | 326 * OK -> re-enter this state |
| 330 » * Cancel -> Goto notKnown | 327 * Cancel -> Goto notKnown |
| 331 » */ | 328 */ |
| 332 » { | 329 { |
| 333 » int x = session.WriteMessage(IMB( | 330 int x = session.WriteMessage(IMB( |
| 334 messageText.Text(L"dialog_active_retry"), | 331 messageText.Text(L"dialog_active_retry"), |
| 335 IMB::Box::warning, IMB::ButtonSet::okCancel, IMB::DefaultButton::one | 332 IMB::Box::warning, IMB::ButtonSet::okCancel, IMB::DefaultButton::one
)); |
| 336 )) ; | 333 switch (x) |
| 337 » switch ( x ) | 334 { |
| 338 » { | 335 case IDOK: |
| 339 » case IDOK: | 336 /* |
| 340 » /* | 337 * Refresh our knowledge of whether IE is running. |
| 341 » * Refresh our knowledge of whether IE is running. | 338 * If it is, we display the dialog again. The state doesn't change,
so we just iterate again. |
| 342 » * If it is, we display the dialog again. The state doesn't change,
so we just iterate again. | 339 * If it's not, then the user has closed IE and we're done. |
| 343 » * If it's not, then the user has closed IE and we're done. | 340 */ |
| 344 » */ | 341 iec.Refresh(); |
| 345 » iec.Refresh() ; | 342 if (!iec.IsRunning()) |
| 346 » if ( ! iec.IsRunning() ) | 343 { |
| 347 » { | 344 state = success; |
| 348 » state = success ; | 345 session.Log("User shut down IE manually."); |
| 349 » session.Log( "User shut down IE manually." ) ; | 346 } |
| 350 » } | 347 break; |
| 351 » break ; | 348 case IDCANCEL: |
| 352 » case IDCANCEL: | 349 state = notKnown; |
| 353 » state = notKnown ; | 350 break; |
| 354 » break ; | 351 default: |
| 355 » default: | 352 throw UnexpectedReturnValueFromMessageBox(); |
| 356 » throw UnexpectedReturnValueFromMessageBox() ; | 353 } |
| 357 » } | 354 } |
| 358 » } | 355 break; |
| 359 » break ; | |
| 360 | 356 |
| 361 case automatic: | 357 case automatic: |
| 362 » /* | 358 /* |
| 363 » * Close all known IE instances. | 359 * Close all known IE instances. |
| 364 » * Unlike other cases, this state starts with an action and not a user q
uery. | 360 * Unlike other cases, this state starts with an action and not a user q
uery. |
| 365 » * We first shut down IE, or at least attempt to. | 361 * We first shut down IE, or at least attempt to. |
| 366 » * | 362 * |
| 367 » * Succeeded -> Goto success | 363 * Succeeded -> Goto success |
| 368 » * Failed && interactive -> | 364 * Failed && interactive -> |
| 369 » * Ask user if they would like to try again | 365 * Ask user if they would like to try again |
| 370 » * Retry -> re-enter this state | 366 * Retry -> re-enter this state |
| 371 » * Cancel -> Goto notKnown | 367 * Cancel -> Goto notKnown |
| 372 » * Failed && not interactive -> Goto abort | 368 * Failed && not interactive -> Goto abort |
| 373 » */ | 369 */ |
| 374 » { | 370 { |
| 375 » bool ieWasClosed = iec.ShutDown() ; | 371 bool ieWasClosed = iec.ShutDown(); |
| 376 » if ( iec.IsRunning() ) | 372 if (iec.IsRunning()) |
| 377 » { | 373 { |
| 378 » session.Log( "Attempt to shut down IE automatically failed." ) ; | 374 session.Log("Attempt to shut down IE automatically failed."); |
| 379 » if ( interactive ) | 375 if (interactive) |
| 380 » { | 376 { |
| 381 » // Assert Interactive session and IE did not shut down. | 377 // Assert Interactive session and IE did not shut down. |
| 382 » int x = session.WriteMessage(IMB( | 378 int x = session.WriteMessage(IMB( |
| 383 messageText.Text(L"dialog_automatic_retry"), | 379 messageText.Text(L"dialog_automatic_retry"), |
| 384 IMB::Box::warning, IMB::ButtonSet::retryCancel, IMB::DefaultButt
on::one | 380 IMB::Box::warning, IMB::ButtonSet::retryCancel, IMB::DefaultButt
on::one)); |
| 385 )) ; | 381 switch (x) |
| 386 » switch ( x ) | 382 { |
| 387 » { | 383 case IDRETRY: |
| 388 » case IDRETRY: | 384 // Don't change the state. Iterate again. |
| 389 » » // Don't change the state. Iterate again. | 385 break; |
| 390 » » break ; | 386 case IDCANCEL: |
| 391 » case IDCANCEL: | 387 state = notKnown; |
| 392 » » state = notKnown ; | 388 break; |
| 393 » » break ; | 389 default: |
| 394 » default: | 390 throw UnexpectedReturnValueFromMessageBox(); |
| 395 » » throw UnexpectedReturnValueFromMessageBox() ; | 391 } |
| 396 » } | 392 } |
| 397 » } | 393 else |
| 398 » else | 394 { |
| 399 » { | 395 // Assert Non-interactive session and IE did not shut down. |
| 400 » // Assert Non-interactive session and IE did not shut down. | 396 state = abort; |
| 401 » state = abort ; | 397 session.Log("Failed to shut down IE automatically."); |
| 402 » session.Log( "Failed to shut down IE automatically." ) ; | 398 } |
| 403 » } | 399 } |
| 404 » } | 400 else |
| 405 » else | 401 { |
| 406 » { | 402 // Assert IE is not running, so ShutDown() succeeded. |
| 407 » // Assert IE is not running, so ShutDown() succeeded. | 403 state = success; |
| 408 » state = success ; | 404 session.Log("Automatically shut down IE."); |
| 409 » session.Log( "Automatically shut down IE." ) ; | 405 } |
| 410 » } | 406 } |
| 411 » } | 407 break; |
| 412 » break; | |
| 413 } | 408 } |
| 414 } | 409 } |
| 415 /* | 410 /* |
| 416 * State machine: Actions for terminal states. | 411 * State machine: Actions for terminal states. |
| 417 */ | 412 */ |
| 418 switch ( state ) | 413 switch (state) |
| 419 { | 414 { |
| 420 case success: | 415 case success: |
| 421 » if ( iec.IsRunning() ) | 416 if (iec.IsRunning()) |
| 422 » { | 417 { |
| 423 » browserRunning = L"1" ; | 418 browserRunning = L"1"; |
| 424 » browserClosed = L"0" ; | 419 browserClosed = L"0"; |
| 425 » } | 420 } |
| 426 » else | 421 else |
| 427 » { | 422 { |
| 428 » browserRunning = L"0" ; | 423 browserRunning = L"0"; |
| 429 » browserClosed = L"1" ; | 424 browserClosed = L"1"; |
| 430 » } | 425 } |
| 431 » return ERROR_SUCCESS ; | 426 return ERROR_SUCCESS; |
| 432 » break; | 427 break; |
| 433 case abort: | 428 case abort: |
| 434 » return ERROR_INSTALL_USEREXIT ; | 429 return ERROR_INSTALL_USEREXIT; |
| 435 » break; | 430 break; |
| 436 } | 431 } |
| 437 } | 432 } |
| 438 catch( std::exception & e ) | 433 catch (std::exception& e) |
| 439 { | 434 { |
| 440 session.LogNoexcept( "terminated by exception: " + std::string( e.what() ) )
; | 435 session.LogNoexcept("terminated by exception: " + std::string(e.what())); |
| 441 return ERROR_INSTALL_FAILURE ; | 436 return ERROR_INSTALL_FAILURE; |
| 442 } | 437 } |
| 443 catch( ... ) | 438 catch (...) |
| 444 { | 439 { |
| 445 session.LogNoexcept( "terminated by unknown exception" ) ; | 440 session.LogNoexcept("terminated by unknown exception"); |
| 446 return ERROR_INSTALL_FAILURE ; | 441 return ERROR_INSTALL_FAILURE; |
| 447 } | 442 } |
| 448 // Should be unreachable. | 443 // Should be unreachable. |
| 449 return ERROR_INSTALL_FAILURE ; | 444 return ERROR_INSTALL_FAILURE; |
| 450 } | 445 } |
| OLD | NEW |