1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "build/intsafe_workaround.h"
13 #include "base/at_exit.h"
14 #include "base/command_line.h"
15 #include "base/file_util.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/process/kill.h"
18 #include "base/strings/string16.h"
19 #include "base/win/scoped_com_initializer.h"
20 #include "base/win/scoped_handle.h"
21 #include "breakpad/src/client/windows/handler/exception_handler.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "win8/delegate_execute/command_execute_impl.h"
24 #include "win8/delegate_execute/crash_server_init.h"
25 #include "win8/delegate_execute/delegate_execute_operation.h"
26 #include "win8/delegate_execute/resource.h"
30 class DelegateExecuteModule
31 : public ATL::CAtlExeModuleT
< DelegateExecuteModule
> {
33 typedef ATL::CAtlExeModuleT
<DelegateExecuteModule
> ParentClass
;
35 HRESULT
RegisterServer(BOOL reg_type_lib
) {
36 return ParentClass::RegisterServer(FALSE
);
39 virtual HRESULT
AddCommonRGSReplacements(IRegistrarBase
* registrar
) throw() {
40 AtlTrace(L
"In %hs\n", __FUNCTION__
);
41 HRESULT hr
= ParentClass::AddCommonRGSReplacements(registrar
);
45 wchar_t delegate_execute_clsid
[MAX_PATH
] = {0};
46 if (!StringFromGUID2(__uuidof(CommandExecuteImpl
), delegate_execute_clsid
,
47 ARRAYSIZE(delegate_execute_clsid
))) {
52 hr
= registrar
->AddReplacement(L
"DELEGATE_EXECUTE_CLSID",
53 delegate_execute_clsid
);
54 ATLASSERT(SUCCEEDED(hr
));
59 DelegateExecuteModule _AtlModule
;
61 using delegate_execute::DelegateExecuteOperation
;
62 using base::win::ScopedHandle
;
64 int RelaunchChrome(const DelegateExecuteOperation
& operation
) {
65 AtlTrace("Relaunching [%ls] with flags [%s]\n",
66 operation
.mutex().c_str(), operation
.relaunch_flags());
67 ScopedHandle
mutex(OpenMutexW(SYNCHRONIZE
, FALSE
, operation
.mutex().c_str()));
68 if (mutex
.IsValid()) {
69 const int kWaitSeconds
= 5;
70 DWORD result
= ::WaitForSingleObject(mutex
, kWaitSeconds
* 1000);
71 if (result
== WAIT_ABANDONED
) {
72 // This is the normal case. Chrome exits and windows marks the mutex as
74 } else if (result
== WAIT_OBJECT_0
) {
75 // This is unexpected. Check if somebody is not closing the mutex on
76 // RelaunchChromehelper, the mutex should not be closed.
77 AtlTrace("Unexpected release of the relaunch mutex!!\n");
78 } else if (result
== WAIT_TIMEOUT
) {
79 // This could mean that Chrome is hung. Proceed to exterminate.
80 DWORD pid
= operation
.GetParentPid();
81 AtlTrace("%ds timeout. Killing Chrome %d\n", kWaitSeconds
, pid
);
82 base::KillProcessById(pid
, 0, false);
84 AtlTrace("Failed to wait for relaunch mutex, result is 0x%x\n", result
);
87 // It is possible that chrome exits so fast that the mutex is not there.
88 AtlTrace("No relaunch mutex found\n");
91 base::win::ScopedCOMInitializer com_initializer
;
93 string16
relaunch_flags(operation
.relaunch_flags());
94 SHELLEXECUTEINFO sei
= { sizeof(sei
) };
95 sei
.fMask
= SEE_MASK_FLAG_LOG_USAGE
;
96 sei
.nShow
= SW_SHOWNORMAL
;
97 sei
.lpFile
= operation
.shortcut().value().c_str();
98 sei
.lpParameters
= relaunch_flags
.c_str();
100 AtlTrace(L
"Relaunching Chrome via shortcut [%ls]\n", sei
.lpFile
);
102 if (!::ShellExecuteExW(&sei
)) {
103 int error
= HRESULT_FROM_WIN32(::GetLastError());
104 AtlTrace("ShellExecute returned 0x%08X\n", error
);
110 extern "C" int WINAPI
_tWinMain(HINSTANCE
, HINSTANCE
, LPTSTR
, int nShowCmd
) {
111 scoped_ptr
<google_breakpad::ExceptionHandler
> breakpad
=
112 delegate_execute::InitializeCrashReporting();
114 base::AtExitManager exit_manager
;
115 AtlTrace("delegate_execute enter\n");
117 CommandLine::Init(0, NULL
);
118 HRESULT ret_code
= E_UNEXPECTED
;
119 DelegateExecuteOperation operation
;
120 if (operation
.Init(CommandLine::ForCurrentProcess())) {
121 switch (operation
.operation_type()) {
122 case DelegateExecuteOperation::DELEGATE_EXECUTE
:
123 ret_code
= _AtlModule
.WinMain(nShowCmd
);
125 case DelegateExecuteOperation::RELAUNCH_CHROME
:
126 ret_code
= RelaunchChrome(operation
);
132 AtlTrace("delegate_execute exit, code = %d\n", ret_code
);