OLD | NEW |
| (Empty) |
1 // Copyright 2009-2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include "omaha/client/install_apps.h" | |
17 #include <atlsafe.h> | |
18 #include "base/scoped_ptr.h" | |
19 #include "omaha/base/const_object_names.h" | |
20 #include "omaha/base/debug.h" | |
21 #include "omaha/base/error.h" | |
22 #include "omaha/base/logging.h" | |
23 #include "omaha/base/reactor.h" | |
24 #include "omaha/base/scope_guard.h" | |
25 #include "omaha/base/scoped_ptr_address.h" | |
26 #include "omaha/base/shutdown_callback.h" | |
27 #include "omaha/base/shutdown_handler.h" | |
28 #include "omaha/base/string.h" | |
29 #include "omaha/base/time.h" | |
30 #include "omaha/base/utils.h" | |
31 #include "omaha/base/vista_utils.h" | |
32 #include "omaha/client/bundle_creator.h" | |
33 #include "omaha/client/bundle_installer.h" | |
34 #include "omaha/client/client_metrics.h" | |
35 #include "omaha/client/client_utils.h" | |
36 #include "omaha/client/help_url_builder.h" | |
37 #include "omaha/client/install_apps_internal.h" | |
38 #include "omaha/client/install_progress_observer.h" | |
39 #include "omaha/client/resource.h" | |
40 #include "omaha/common/command_line.h" | |
41 #include "omaha/common/config_manager.h" | |
42 #include "omaha/common/const_cmd_line.h" | |
43 #include "omaha/common/goopdate_utils.h" | |
44 #include "omaha/common/lang.h" | |
45 #include "omaha/common/ping.h" | |
46 #include "omaha/common/update3_utils.h" | |
47 #include "goopdate/omaha3_idl.h" | |
48 #include "omaha/ui/progress_wnd.h" | |
49 | |
50 namespace omaha { | |
51 | |
52 namespace { | |
53 | |
54 // Implements the UI progress window. | |
55 class SilentProgressObserver : public InstallProgressObserver { | |
56 public: | |
57 explicit SilentProgressObserver(BundleInstaller* installer) | |
58 : installer_(installer) { | |
59 ASSERT1(installer); | |
60 } | |
61 | |
62 virtual void OnCheckingForUpdate() { | |
63 CORE_LOG(L3, (_T("[SilentProgressObserver::OnCheckingForUpdate]"))); | |
64 } | |
65 | |
66 virtual void OnUpdateAvailable(const CString& app_name, | |
67 const CString& version_string) { | |
68 CORE_LOG(L3, (_T("[SilentProgressObserver::OnUpdateAvailable][%s][%s]"), | |
69 app_name, version_string)); | |
70 UNREFERENCED_PARAMETER(app_name); | |
71 UNREFERENCED_PARAMETER(version_string); | |
72 } | |
73 | |
74 virtual void OnWaitingToDownload(const CString& app_name) { | |
75 CORE_LOG(L3, (_T("[SilentProgressObserver::OnWaitingToDownload][%s]"), | |
76 app_name)); | |
77 UNREFERENCED_PARAMETER(app_name); | |
78 } | |
79 | |
80 virtual void OnDownloading(const CString& app_name, | |
81 int time_remaining_ms, | |
82 int pos) { | |
83 CORE_LOG(L5, (_T("[SilentProgressObserver::OnDownloading]") | |
84 _T("[%s][remaining ms=%d][pos=%d]"), | |
85 app_name, time_remaining_ms, pos)); | |
86 UNREFERENCED_PARAMETER(app_name); | |
87 UNREFERENCED_PARAMETER(time_remaining_ms); | |
88 UNREFERENCED_PARAMETER(pos); | |
89 } | |
90 | |
91 virtual void OnWaitingRetryDownload(const CString& app_name, | |
92 time64 next_retry_time) { | |
93 CORE_LOG(L5, (_T("[SilentProgressObserver::OnWaitingRetryDownload]") | |
94 _T("[%s][next retry time=%llu]"), | |
95 app_name, next_retry_time)); | |
96 UNREFERENCED_PARAMETER(app_name); | |
97 UNREFERENCED_PARAMETER(next_retry_time); | |
98 } | |
99 | |
100 virtual void OnWaitingToInstall(const CString& app_name, | |
101 bool* can_start_install) { | |
102 CORE_LOG(L3, (_T("[SilentProgressObserver::OnWaitingToInstall][%s]"), | |
103 app_name)); | |
104 ASSERT1(can_start_install); | |
105 UNREFERENCED_PARAMETER(app_name); | |
106 UNREFERENCED_PARAMETER(can_start_install); | |
107 } | |
108 | |
109 virtual void OnInstalling(const CString& app_name) { | |
110 CORE_LOG(L5, (_T("[SilentProgressObserver::OnInstalling][%s]"), app_name)); | |
111 UNREFERENCED_PARAMETER(app_name); | |
112 } | |
113 | |
114 virtual void OnPause() { | |
115 CORE_LOG(L3, (_T("[SilentProgressObserver::OnPause]"))); | |
116 } | |
117 | |
118 // Terminates the message loop. | |
119 virtual void OnComplete(const ObserverCompletionInfo& observer_info) { | |
120 CORE_LOG(L3, (_T("[SilentProgressObserver::OnComplete][%s]"), | |
121 observer_info.ToString())); | |
122 UNREFERENCED_PARAMETER(observer_info); | |
123 | |
124 installer_->DoExit(); | |
125 CORE_LOG(L1, (_T("[SilentProgressObserver][DoExit() called]"))); | |
126 } | |
127 | |
128 private: | |
129 BundleInstaller *const installer_; | |
130 }; | |
131 | |
132 class OnDemandEvents : public OnDemandEventsInterface { | |
133 public: | |
134 explicit OnDemandEvents(BundleInstaller* installer) | |
135 : installer_(installer) { | |
136 ASSERT1(installer); | |
137 } | |
138 virtual void DoClose() { | |
139 installer_->DoClose(); | |
140 } | |
141 virtual void DoExit() { | |
142 installer_->DoExit(); | |
143 } | |
144 | |
145 private: | |
146 BundleInstaller *const installer_; | |
147 }; | |
148 | |
149 // This ATL module is used for BundleInstaller message loop shutdown intrinsics. | |
150 // It is also needed for cases where the Update3 server COM objects are created | |
151 // inproc. | |
152 class BundleAtlModule : public CAtlExeModuleT<BundleAtlModule> { | |
153 public: | |
154 explicit BundleAtlModule() : allow_post_quit_(false) { | |
155 // Disable the delay on shutdown mechanism in CAtlExeModuleT. | |
156 m_bDelayShutdown = false; | |
157 } | |
158 ~BundleAtlModule() {} | |
159 | |
160 LONG Unlock() throw() { | |
161 LONG lRet = CComGlobalsThreadModel::Decrement(&m_nLockCnt); | |
162 | |
163 if (lRet == 0 && allow_post_quit_) { | |
164 ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); | |
165 } | |
166 | |
167 return lRet; | |
168 } | |
169 | |
170 // BundleAtlModule will only post WM_QUIT if enable_quit() is called, to avoid | |
171 // spurious WM_QUITs during bundle initialization. | |
172 void enable_quit() { | |
173 allow_post_quit_ = true; | |
174 } | |
175 | |
176 private: | |
177 bool allow_post_quit_; | |
178 | |
179 DISALLOW_COPY_AND_ASSIGN(BundleAtlModule); | |
180 }; | |
181 | |
182 } // namespace | |
183 | |
184 namespace internal { | |
185 | |
186 bool IsBrowserRestartSupported(BrowserType browser_type) { | |
187 return (browser_type != BROWSER_UNKNOWN && | |
188 browser_type != BROWSER_DEFAULT && | |
189 browser_type < BROWSER_MAX); | |
190 } | |
191 | |
192 InstallAppsWndEvents::InstallAppsWndEvents(bool is_machine, | |
193 BundleInstaller* installer, | |
194 BrowserType browser_type) | |
195 : is_machine_(is_machine), | |
196 installer_(installer), | |
197 browser_type_(browser_type) { | |
198 ASSERT1(installer_); | |
199 } | |
200 | |
201 void InstallAppsWndEvents::DoClose() { | |
202 ASSERT1(installer_); | |
203 installer_->DoClose(); | |
204 } | |
205 | |
206 void InstallAppsWndEvents::DoExit() { | |
207 ASSERT1(installer_); | |
208 installer_->DoExit(); | |
209 } | |
210 | |
211 void InstallAppsWndEvents::DoCancel() { | |
212 ASSERT1(installer_); | |
213 installer_->DoCancel(); | |
214 } | |
215 | |
216 // TODO(omaha3): Need to address elevated Vista installs. Since we are doing | |
217 // a handoff, we know that Omaha is installed and can do de-elevation. | |
218 // However, BuildGetHelpUrl will return an empty string right now. Best to | |
219 // just solve the general problem. | |
220 bool InstallAppsWndEvents::DoLaunchBrowser(const CString& url) { | |
221 CORE_LOG(L2, (_T("[InstallAppsWndEvents::DoLaunchBrowser %s]"), url)); | |
222 const BrowserType browser = BROWSER_UNKNOWN == browser_type_ ? | |
223 BROWSER_DEFAULT : | |
224 browser_type_; | |
225 return SUCCEEDED(goopdate_utils::LaunchBrowser(is_machine_, browser, url)); | |
226 } | |
227 | |
228 // Restarts the browser(s) and returns whether the browser was successfully | |
229 // restarted. | |
230 bool InstallAppsWndEvents::DoRestartBrowser(bool terminate_all_browsers, | |
231 const std::vector<CString>& urls) { | |
232 // UI should not trigger this call back if the browser type is unknown. | |
233 // Instead it should ask user to restart the browser(s) manually. | |
234 ASSERT1(IsBrowserRestartSupported(browser_type_)); | |
235 | |
236 BrowserType browser = browser_type_; | |
237 if (browser == BROWSER_DEFAULT) { | |
238 GetDefaultBrowserType(&browser); | |
239 } | |
240 | |
241 TerminateBrowserResult browser_res; | |
242 TerminateBrowserResult default_res; | |
243 if (terminate_all_browsers) { | |
244 VERIFY1(SUCCEEDED(goopdate_utils::TerminateAllBrowsers(browser, | |
245 &browser_res, | |
246 &default_res))); | |
247 } else { | |
248 VERIFY1(SUCCEEDED(goopdate_utils::TerminateBrowserProcesses(browser, | |
249 &browser_res, | |
250 &default_res))); | |
251 } | |
252 | |
253 BrowserType default_browser_type = BROWSER_UNKNOWN; | |
254 HRESULT hr = GetDefaultBrowserType(&default_browser_type); | |
255 if (FAILED(hr)) { | |
256 CORE_LOG(LE, (_T("[GetDefaultBrowserType failed][0x%08x]"), hr)); | |
257 } | |
258 | |
259 BrowserType browser_to_restart = BROWSER_UNKNOWN; | |
260 if (!goopdate_utils::GetBrowserToRestart(browser, | |
261 default_browser_type, | |
262 browser_res, | |
263 default_res, | |
264 &browser_to_restart)) { | |
265 CORE_LOG(LE, (_T("[GetBrowserToRestart returned false. Not launching.]"))); | |
266 return false; | |
267 } | |
268 ASSERT1(IsBrowserRestartSupported(browser_to_restart)); | |
269 | |
270 bool succeeded = true; | |
271 for (size_t i = 0; i < urls.size(); ++i) { | |
272 succeeded &= SUCCEEDED(goopdate_utils::LaunchBrowser(is_machine_, | |
273 browser_to_restart, | |
274 urls[i])); | |
275 } | |
276 | |
277 return succeeded; | |
278 } | |
279 | |
280 // Initiates a reboot and returns whether it was iniated successfully. | |
281 bool InstallAppsWndEvents::DoReboot() { | |
282 ASSERT(false, (_T("Not implemented."))); | |
283 return false; | |
284 } | |
285 | |
286 CString GetBundleDisplayName(IAppBundle* app_bundle) { | |
287 if (!app_bundle) { | |
288 return client_utils::GetDefaultBundleName(); | |
289 } | |
290 | |
291 CComBSTR bundle_name; | |
292 HRESULT hr = app_bundle->get_displayName(&bundle_name); | |
293 if (FAILED(hr)) { | |
294 CORE_LOG(LW, (_T("[get_displayName failed][0x%08x]"), hr)); | |
295 } | |
296 | |
297 return (SUCCEEDED(hr) && bundle_name.Length()) ? | |
298 CString(bundle_name) : client_utils::GetDefaultBundleName(); | |
299 } | |
300 | |
301 HRESULT CreateClientUI(bool is_machine, | |
302 BrowserType browser_type, | |
303 BundleInstaller* installer, | |
304 IAppBundle* app_bundle, | |
305 InstallProgressObserver** observer, | |
306 OmahaWndEvents** ui_sink) { | |
307 ASSERT1(installer); | |
308 ASSERT1(observer); | |
309 ASSERT1(!*observer); | |
310 ASSERT1(ui_sink); | |
311 ASSERT1(!*ui_sink); | |
312 | |
313 scoped_ptr<ProgressWnd> progress_wnd( | |
314 new ProgressWnd(installer->message_loop(), NULL)); | |
315 ScopeGuard destroy_window_guard = MakeObjGuard(*progress_wnd, | |
316 &ProgressWnd::DestroyWindow); | |
317 | |
318 progress_wnd->set_is_machine(is_machine); | |
319 progress_wnd->set_bundle_name(internal::GetBundleDisplayName(app_bundle)); | |
320 | |
321 HRESULT hr = progress_wnd->Initialize(); | |
322 if (FAILED(hr)) { | |
323 return hr; | |
324 } | |
325 | |
326 scoped_ptr<internal::InstallAppsWndEvents> progress_wnd_events( | |
327 new internal::InstallAppsWndEvents(is_machine, installer, browser_type)); | |
328 progress_wnd->SetEventSink(progress_wnd_events.get()); | |
329 | |
330 progress_wnd->Show(); | |
331 installer->SetBundleParentWindow(progress_wnd->m_hWnd); | |
332 | |
333 destroy_window_guard.Dismiss(); | |
334 *observer = progress_wnd.release(); | |
335 *ui_sink = progress_wnd_events.release(); | |
336 return S_OK; | |
337 } | |
338 | |
339 // The order of construction is important because it ensures the objects are | |
340 // deleted in a safe order (objects before their dependencies). | |
341 // Any early returns before the message loop is run must call | |
342 // progress_wnd.DestroyWindow(). Errors do not need to be reported in a UI | |
343 // because they are handled further up the call stack. | |
344 HRESULT DoInstallApps(BundleInstaller* installer, | |
345 IAppBundle* app_bundle, | |
346 bool is_machine, | |
347 bool is_interactive, | |
348 bool is_update_all_apps, | |
349 BrowserType browser_type, | |
350 bool* has_ui_been_displayed) { | |
351 CORE_LOG(L2, (_T("[DoInstallApps]"))); | |
352 ASSERT1(installer); | |
353 ASSERT1(has_ui_been_displayed); | |
354 | |
355 scoped_ptr<InstallProgressObserver> observer; | |
356 scoped_ptr<OmahaWndEvents> ui_sink; | |
357 bool listen_to_shutdown_event = false; | |
358 | |
359 CComPtr<IAppBundle> app_bundle_ptr; | |
360 app_bundle_ptr.Attach(app_bundle); | |
361 | |
362 HRESULT hr = S_OK; | |
363 if (is_interactive) { | |
364 hr = CreateClientUI(is_machine, | |
365 browser_type, | |
366 installer, | |
367 app_bundle, | |
368 address(observer), | |
369 address(ui_sink)); | |
370 if (FAILED(hr)) { | |
371 CORE_LOG(LE, (_T("CreateClientUI failed][0x%08x]"), hr)); | |
372 return hr; | |
373 } | |
374 *has_ui_been_displayed = true; | |
375 } else { | |
376 observer.reset(new SilentProgressObserver(installer)); | |
377 if (is_update_all_apps) { | |
378 listen_to_shutdown_event = true; | |
379 } | |
380 } | |
381 | |
382 hr = installer->InstallBundle(is_machine, | |
383 listen_to_shutdown_event, | |
384 app_bundle_ptr.Detach(), | |
385 observer.get()); | |
386 | |
387 observer.reset(); | |
388 | |
389 // ui_sink must be destroyed after observer and before installer. | |
390 ui_sink.reset(); | |
391 | |
392 CORE_LOG(L1, (_T("DoInstallApps returning][0x%08x]"), hr)); | |
393 return hr; | |
394 } | |
395 | |
396 void HandleInstallAppsError(HRESULT error, | |
397 int extra_code1, | |
398 bool is_machine, | |
399 bool is_interactive, | |
400 bool is_eula_accepted, | |
401 bool is_oem_install, | |
402 const CString& install_source, | |
403 const CommandLineExtraArgs& extra_args, | |
404 const CString& session_id, | |
405 bool* has_ui_been_displayed) { | |
406 ASSERT1(FAILED(error)); | |
407 ASSERT1(has_ui_been_displayed); | |
408 | |
409 const CString& bundle_name = extra_args.bundle_name; | |
410 ASSERT1(!bundle_name.IsEmpty()); | |
411 | |
412 CString error_text; | |
413 | |
414 switch (error) { | |
415 case GOOPDATE_E_USER_AND_ELEVATED_WITH_UAC_ON: | |
416 error_text.FormatMessage(IDS_USER_SHOULD_NOT_RUN_ELEVATED_WITH_UAC_ON, | |
417 bundle_name); | |
418 break; | |
419 default: { | |
420 CString product_name; | |
421 VERIFY1(product_name.LoadString(IDS_PRODUCT_DISPLAY_NAME)); | |
422 error_text.FormatMessage(IDS_SETUP_FAILED, product_name, error); | |
423 break; | |
424 } | |
425 } | |
426 | |
427 OPT_LOG(LE, (_T("[Failed to install apps][0x%08x][%s]"), error, error_text)); | |
428 | |
429 if (is_interactive && !*has_ui_been_displayed) { | |
430 CString primary_app_id; | |
431 if (!extra_args.apps.empty()) { | |
432 primary_app_id = GuidToString(extra_args.apps[0].app_guid); | |
433 } | |
434 | |
435 *has_ui_been_displayed = client_utils::DisplayError( | |
436 is_machine, | |
437 bundle_name, | |
438 error, | |
439 extra_code1, | |
440 error_text, | |
441 primary_app_id, | |
442 extra_args.language, | |
443 extra_args.installation_id, | |
444 extra_args.brand_code); | |
445 } | |
446 | |
447 if (!is_eula_accepted || is_oem_install) { | |
448 return; | |
449 } | |
450 | |
451 // Send an install complete ping and do not wait for the ping to be sent. | |
452 // Since Omaha has been installed at this point, it should be able to | |
453 // send this ping without blocking the user flow. | |
454 Ping ping(is_machine, session_id, install_source); | |
455 ping.LoadAppDataFromExtraArgs(extra_args); | |
456 PingEventPtr ping_event( | |
457 new PingEvent(PingEvent::EVENT_INSTALL_COMPLETE, | |
458 PingEvent::EVENT_RESULT_HANDOFF_ERROR, | |
459 error, | |
460 extra_code1)); | |
461 ping.BuildAppsPing(ping_event); | |
462 HRESULT send_result = ping.Send(true); | |
463 if (FAILED(send_result)) { | |
464 CORE_LOG(LW, (_T("[Ping::Send failed][0x%x]"), send_result)); | |
465 } | |
466 } | |
467 | |
468 } // namespace internal | |
469 | |
470 HRESULT UpdateAppOnDemand(bool is_machine, | |
471 const CString& app_id, | |
472 bool is_update_check_only, | |
473 const CString& session_id, | |
474 HANDLE impersonation_token, | |
475 HANDLE primary_token, | |
476 OnDemandObserver* observer) { | |
477 CORE_LOG(L2, (_T("[UpdateAppOnDemand][%d][%s][%d]"), | |
478 is_machine, app_id, is_update_check_only)); | |
479 | |
480 const TCHAR* install_source = is_update_check_only ? | |
481 kCmdLineInstallSource_OnDemandCheckForUpdate : | |
482 kCmdLineInstallSource_OnDemandUpdate; | |
483 CComPtr<IAppBundle> app_bundle; | |
484 HRESULT hr = bundle_creator::CreateForOnDemand(is_machine, | |
485 app_id, | |
486 install_source, | |
487 session_id, | |
488 impersonation_token, | |
489 primary_token, | |
490 &app_bundle); | |
491 if (SUCCEEDED(hr)) { | |
492 BundleInstaller installer(NULL, // No help URL for on-demand. | |
493 false, // Is not update all apps. | |
494 is_update_check_only, | |
495 false); | |
496 hr = installer.Initialize(); | |
497 if (SUCCEEDED(hr)) { | |
498 OnDemandEvents install_events(&installer); | |
499 observer->SetEventSink(&install_events); | |
500 | |
501 // TODO(omaha3): Listen to shutdown event during installation? | |
502 return installer.InstallBundle(is_machine, | |
503 false, | |
504 app_bundle.Detach(), | |
505 observer); | |
506 } | |
507 } | |
508 | |
509 // The observer must be notified that the bundle has completed with an error | |
510 // since the bundle will not be processed. | |
511 observer->OnComplete(ObserverCompletionInfo(COMPLETION_CODE_ERROR)); | |
512 return hr; | |
513 } | |
514 | |
515 HRESULT InstallApps(bool is_machine, | |
516 bool is_interactive, | |
517 bool is_eula_accepted, | |
518 bool is_oem_install, | |
519 bool is_offline, | |
520 const CString& offline_directory, | |
521 const CommandLineExtraArgs& extra_args, | |
522 const CString& install_source, | |
523 const CString& session_id, | |
524 bool* has_ui_been_displayed) { | |
525 CORE_LOG(L2, (_T("[InstallApps][is_machine: %u][is_interactive: %u]") | |
526 _T("[is_eula_accepted: %u][is_oem_install: %u][is_offline: %u]") | |
527 _T("[offline_directory: %s]"), is_machine, is_interactive, | |
528 is_eula_accepted, is_oem_install, is_offline, offline_directory)); | |
529 ASSERT1(has_ui_been_displayed); | |
530 | |
531 BundleAtlModule atl_module; | |
532 | |
533 CComPtr<IAppBundle> app_bundle; | |
534 HRESULT hr = bundle_creator::CreateFromCommandLine(is_machine, | |
535 is_eula_accepted, | |
536 is_offline, | |
537 offline_directory, | |
538 extra_args, | |
539 install_source, | |
540 session_id, | |
541 is_interactive, | |
542 &app_bundle); | |
543 if (FAILED(hr)) { | |
544 CORE_LOG(LE, (_T("[bundle_creator::CreateFromCommandLine][0x%08x]"), hr)); | |
545 internal::HandleInstallAppsError(hr, | |
546 0, | |
547 is_machine, | |
548 is_interactive, | |
549 is_eula_accepted, | |
550 is_oem_install, | |
551 install_source, | |
552 extra_args, | |
553 session_id, | |
554 has_ui_been_displayed); | |
555 return hr; | |
556 } | |
557 | |
558 BundleInstaller installer( | |
559 new HelpUrlBuilder(is_machine, | |
560 extra_args.language, | |
561 extra_args.installation_id, | |
562 extra_args.brand_code), | |
563 false, // is_update_all_apps | |
564 false, // is_update_check_only | |
565 internal::IsBrowserRestartSupported(extra_args.browser_type)); | |
566 hr = installer.Initialize(); | |
567 if (FAILED(hr)) { | |
568 return hr; | |
569 } | |
570 | |
571 atl_module.enable_quit(); | |
572 return internal::DoInstallApps(&installer, | |
573 app_bundle.Detach(), | |
574 is_machine, | |
575 is_interactive, | |
576 false, // Is not update all apps. | |
577 extra_args.browser_type, | |
578 has_ui_been_displayed); | |
579 } | |
580 | |
581 HRESULT UpdateAllApps(bool is_machine, | |
582 bool is_interactive, | |
583 const CString& install_source, | |
584 const CString& display_language, | |
585 const CString& session_id, | |
586 bool* has_ui_been_displayed) { | |
587 CORE_LOG(L2, (_T("[UpdateAllApps][%u][%u]"), is_machine, is_interactive)); | |
588 ASSERT1(has_ui_been_displayed); | |
589 | |
590 BundleAtlModule atl_module; | |
591 | |
592 CComPtr<IAppBundle> app_bundle; | |
593 HRESULT hr = bundle_creator::Create(is_machine, | |
594 display_language, | |
595 install_source, | |
596 session_id, | |
597 is_interactive, | |
598 &app_bundle); | |
599 if (FAILED(hr)) { | |
600 CORE_LOG(LE, (_T("[bundle_creator::Create failed][0x%08x]"), hr)); | |
601 return hr; | |
602 } | |
603 | |
604 BundleInstaller installer(new HelpUrlBuilder(is_machine, | |
605 display_language, | |
606 GUID_NULL, | |
607 CString()), | |
608 true, // is_update_all_apps | |
609 false, // is_update_check_only | |
610 BROWSER_UNKNOWN); | |
611 hr = installer.Initialize(); | |
612 if (FAILED(hr)) { | |
613 return hr; | |
614 } | |
615 | |
616 atl_module.enable_quit(); | |
617 return internal::DoInstallApps(&installer, | |
618 app_bundle.Detach(), | |
619 is_machine, | |
620 is_interactive, | |
621 true, // Is update all apps. | |
622 BROWSER_UNKNOWN, | |
623 has_ui_been_displayed); | |
624 } | |
625 | |
626 } // namespace omaha | |
OLD | NEW |