15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "build/intsafe_workaround.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlbase.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlcom.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <atlctl.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <initguid.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <shellapi.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/at_exit.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 17bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/kill.h" 187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string16.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "breakpad/src/client/windows/handler/exception_handler.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "win8/delegate_execute/command_execute_impl.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "win8/delegate_execute/crash_server_init.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "win8/delegate_execute/delegate_execute_operation.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "win8/delegate_execute/resource.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ATL; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DelegateExecuteModule 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public ATL::CAtlExeModuleT< DelegateExecuteModule > { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public : 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef ATL::CAtlExeModuleT<DelegateExecuteModule> ParentClass; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT RegisterServer(BOOL reg_type_lib) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ParentClass::RegisterServer(FALSE); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* registrar) throw() { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace(L"In %hs\n", __FUNCTION__); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT hr = ParentClass::AddCommonRGSReplacements(registrar); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t delegate_execute_clsid[MAX_PATH] = {0}; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!StringFromGUID2(__uuidof(CommandExecuteImpl), delegate_execute_clsid, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ARRAYSIZE(delegate_execute_clsid))) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ATLASSERT(false); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return E_FAIL; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hr = registrar->AddReplacement(L"DELEGATE_EXECUTE_CLSID", 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_execute_clsid); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ATLASSERT(SUCCEEDED(hr)); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hr; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DelegateExecuteModule _AtlModule; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using delegate_execute::DelegateExecuteOperation; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedHandle; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int RelaunchChrome(const DelegateExecuteOperation& operation) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace("Relaunching [%ls] with flags [%s]\n", 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) operation.mutex().c_str(), operation.relaunch_flags()); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedHandle mutex(OpenMutexW(SYNCHRONIZE, FALSE, operation.mutex().c_str())); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mutex.IsValid()) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kWaitSeconds = 5; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD result = ::WaitForSingleObject(mutex, kWaitSeconds * 1000); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == WAIT_ABANDONED) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is the normal case. Chrome exits and windows marks the mutex as 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // abandoned. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (result == WAIT_OBJECT_0) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is unexpected. Check if somebody is not closing the mutex on 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RelaunchChromehelper, the mutex should not be closed. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace("Unexpected release of the relaunch mutex!!\n"); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (result == WAIT_TIMEOUT) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This could mean that Chrome is hung. Proceed to exterminate. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DWORD pid = operation.GetParentPid(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace("%ds timeout. Killing Chrome %d\n", kWaitSeconds, pid); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::KillProcessById(pid, 0, false); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace("Failed to wait for relaunch mutex, result is 0x%x\n", result); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is possible that chrome exits so fast that the mutex is not there. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace("No relaunch mutex found\n"); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ScopedCOMInitializer com_initializer; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 relaunch_flags(operation.relaunch_flags()); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHELLEXECUTEINFO sei = { sizeof(sei) }; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sei.fMask = SEE_MASK_FLAG_LOG_USAGE; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sei.nShow = SW_SHOWNORMAL; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sei.lpFile = operation.shortcut().value().c_str(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sei.lpParameters = relaunch_flags.c_str(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace(L"Relaunching Chrome via shortcut [%ls]\n", sei.lpFile); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!::ShellExecuteExW(&sei)) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error = HRESULT_FROM_WIN32(::GetLastError()); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace("ShellExecute returned 0x%08X\n", error); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return error; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return S_OK; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" int WINAPI _tWinMain(HINSTANCE , HINSTANCE, LPTSTR, int nShowCmd) { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<google_breakpad::ExceptionHandler> breakpad = 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_execute::InitializeCrashReporting(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AtExitManager exit_manager; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace("delegate_execute enter\n"); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine::Init(0, NULL); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HRESULT ret_code = E_UNEXPECTED; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DelegateExecuteOperation operation; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (operation.Init(CommandLine::ForCurrentProcess())) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (operation.operation_type()) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DelegateExecuteOperation::DELEGATE_EXECUTE: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_code = _AtlModule.WinMain(nShowCmd); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DelegateExecuteOperation::RELAUNCH_CHROME: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret_code = RelaunchChrome(operation); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AtlTrace("delegate_execute exit, code = %d\n", ret_code); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret_code; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 135