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.
4
5#include "chrome_frame/update_launcher.h"
6
7#include <windows.h>
8#include <Shellapi.h>
9
10#include "base/win/scoped_com_initializer.h"
11#include "base/win/scoped_comptr.h"
12#include "base/win/scoped_handle.h"
13#include "google_update/google_update_idl.h"
14
15namespace {
16
17const wchar_t kChromeFrameGuid[] = L"{8BA986DA-5100-405E-AA35-86F34A02ACBF}";
18
19const DWORD kLaunchFailureExitCode = 0xFF;
20
21const wchar_t kUpdateCommandFlag[] = L"--update-cmd";
22
23// Waits indefinitely for the provided process to exit. Returns the process's
24// exit code, or kLaunchFailureExitCode if an error occurs in the waiting.
25DWORD WaitForProcessExitCode(HANDLE handle) {
26  DWORD exit_code = 0;
27  return ((::WaitForSingleObject(handle, INFINITE) == WAIT_OBJECT_0) &&
28          ::GetExitCodeProcess(handle, &exit_code)) ?
29      exit_code : kLaunchFailureExitCode;
30}
31
32}  // namespace
33
34namespace update_launcher {
35
36std::wstring GetUpdateCommandFromArguments(const wchar_t* command_line) {
37  std::wstring command;
38
39  if (command_line != NULL) {
40    int num_args = 0;
41    wchar_t** args = NULL;
42    args = ::CommandLineToArgvW(command_line, &num_args);
43
44    if (args) {
45      if (num_args == 3 && _wcsicmp(args[1], kUpdateCommandFlag) == 0)
46        command = args[2];
47      ::LocalFree(args);
48    }
49  }
50
51  return command;
52}
53
54DWORD LaunchUpdateCommand(const std::wstring& command) {
55  base::win::ScopedCOMInitializer com_initializer;
56  if (!com_initializer.succeeded())
57    return kLaunchFailureExitCode;
58
59  base::win::ScopedComPtr<IProcessLauncher> ipl;
60  if (FAILED(ipl.CreateInstance(__uuidof(ProcessLauncherClass))))
61    return kLaunchFailureExitCode;
62
63  ULONG_PTR phandle = NULL;
64  if (FAILED(ipl->LaunchCmdElevated(kChromeFrameGuid, command.c_str(),
65                                    ::GetCurrentProcessId(), &phandle)))
66    return kLaunchFailureExitCode;
67
68  base::win::ScopedHandle process(reinterpret_cast<HANDLE>(phandle));
69  return WaitForProcessExitCode(process);
70}
71
72}  // namespace process_launcher
73