1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cloud_print/common/win/install_utils.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <windows.h>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/command_line.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/file_util.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/file_version_info_win.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/files/file_path.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/path_service.h"
14bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/launch.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/win/registry.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace cloud_print {
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Google Update related constants.
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kClientsKey[] = L"SOFTWARE\\Google\\Update\\Clients\\";
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kClientStateKey[] = L"SOFTWARE\\Google\\Update\\ClientState\\";
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t* kUsageKey = L"dr";
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kVersionKey[] = L"pv";
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kNameKey[] = L"name";
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const DWORD kInstallerResultFailedCustomError = 1;
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kRegValueInstallerResult[] = L"InstallerResult";
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kRegValueInstallerResultUIString[] = L"InstallerResultUIString";
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Uninstall related constants.
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kUninstallKey[] =
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\";
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kInstallLocation[] = L"InstallLocation";
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kUninstallString[] = L"UninstallString";
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kDisplayVersion[] = L"DisplayVersion";
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kDisplayIcon[] = L"DisplayIcon";
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kDisplayName[] = L"DisplayName";
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kPublisher[] = L"Publisher";
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kNoModify[] = L"NoModify";
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const wchar_t kNoRepair[] = L"NoRepair";
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SetGoogleUpdateKeys(const base::string16& product_id,
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         const base::string16& product_name) {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::win::RegKey key;
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (key.Create(HKEY_LOCAL_MACHINE,
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 (cloud_print::kClientsKey + product_id).c_str(),
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 KEY_SET_VALUE) != ERROR_SUCCESS) {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to open key";
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Get the version from the resource file.
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 version_string;
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<FileVersionInfo> version_info(
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FileVersionInfo::CreateFileVersionInfoForCurrentModule());
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (version_info.get()) {
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FileVersionInfoWin* version_info_win =
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        static_cast<FileVersionInfoWin*>(version_info.get());
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    version_string = version_info_win->product_version();
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to get version string";
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Use a random version string so that Google Update has something to go by.
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    version_string = L"0.0.0.99";
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (key.WriteValue(kVersionKey, version_string.c_str()) != ERROR_SUCCESS ||
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      key.WriteValue(kNameKey, product_name.c_str()) != ERROR_SUCCESS) {
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to set registry keys";
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SetGoogleUpdateError(const base::string16& product_id,
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          const base::string16& message) {
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LOG(ERROR) << message;
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::win::RegKey key;
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (key.Create(HKEY_LOCAL_MACHINE,
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 (cloud_print::kClientStateKey + product_id).c_str(),
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 KEY_SET_VALUE) != ERROR_SUCCESS) {
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to open key";
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (key.WriteValue(kRegValueInstallerResult,
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     kInstallerResultFailedCustomError) != ERROR_SUCCESS ||
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      key.WriteValue(kRegValueInstallerResultUIString,
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     message.c_str()) != ERROR_SUCCESS) {
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(ERROR) << "Unable to set registry keys";
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void DeleteGoogleUpdateKeys(const base::string16& product_id) {
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::win::RegKey key;
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (key.Open(HKEY_LOCAL_MACHINE,
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               (cloud_print::kClientsKey + product_id).c_str(),
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               DELETE) != ERROR_SUCCESS) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to open key to delete";
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (key.DeleteKey(L"") != ERROR_SUCCESS) {
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to delete key";
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void CreateUninstallKey(const base::string16& uninstall_id,
108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                        const base::string16& product_name,
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        const std::string& uninstall_switch) {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Now write the Windows Uninstall entries
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Minimal error checking here since the install can continue
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // if this fails.
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::win::RegKey key;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (key.Create(HKEY_LOCAL_MACHINE,
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 (cloud_print::kUninstallKey + uninstall_id).c_str(),
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 KEY_SET_VALUE) != ERROR_SUCCESS) {
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to open key";
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath unstall_binary;
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(PathService::Get(base::FILE_EXE, &unstall_binary));
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CommandLine uninstall_command(unstall_binary);
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uninstall_command.AppendSwitch(uninstall_switch);
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  key.WriteValue(kUninstallString,
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 uninstall_command.GetCommandLineString().c_str());
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  key.WriteValue(kInstallLocation,
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 unstall_binary.DirName().value().c_str());
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Get the version resource.
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<FileVersionInfo> version_info(
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FileVersionInfo::CreateFileVersionInfoForCurrentModule());
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (version_info.get()) {
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FileVersionInfoWin* version_info_win =
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        static_cast<FileVersionInfoWin*>(version_info.get());
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    key.WriteValue(kDisplayVersion,
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   version_info_win->file_version().c_str());
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    key.WriteValue(kPublisher, version_info_win->company_name().c_str());
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to get version string";
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  key.WriteValue(kDisplayName, product_name.c_str());
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  key.WriteValue(kDisplayIcon, unstall_binary.value().c_str());
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  key.WriteValue(kNoModify, 1);
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  key.WriteValue(kNoRepair, 1);
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void DeleteUninstallKey(const base::string16& uninstall_id) {
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ::RegDeleteKey(HKEY_LOCAL_MACHINE,
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 (cloud_print::kUninstallKey + uninstall_id).c_str());
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::FilePath GetInstallLocation(const base::string16& uninstall_id) {
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::win::RegKey key;
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (key.Open(HKEY_LOCAL_MACHINE,
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               (cloud_print::kUninstallKey + uninstall_id).c_str(),
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               KEY_QUERY_VALUE) != ERROR_SUCCESS) {
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Not installed.
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return base::FilePath();
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 install_path_value;
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  key.ReadValue(kInstallLocation, &install_path_value);
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::FilePath(install_path_value);
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void DeleteProgramDir(const std::string& delete_switch) {
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath installer_source;
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!PathService::Get(base::FILE_EXE, &installer_source))
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Deletes only subdirs of program files.
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!IsProgramsFilesParent(installer_source))
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath temp_path;
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!base::CreateTemporaryFile(&temp_path))
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
1787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::CopyFile(installer_source, temp_path);
1797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::DeleteFileAfterReboot(temp_path);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CommandLine command_line(temp_path);
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  command_line.AppendSwitchPath(delete_switch, installer_source.DirName());
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::LaunchOptions options;
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ProcessHandle process_handle;
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!base::LaunchProcess(command_line, options, &process_handle)) {
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to launch child uninstall.";
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool IsProgramsFilesParent(const base::FilePath& path) {
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath program_files;
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!PathService::Get(base::DIR_PROGRAM_FILESX86, &program_files))
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return program_files.IsParent(path);
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace cloud_print
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
198