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