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/service/win/installer.h"
      6 
      7 #include <winerror.h>
      8 
      9 #include "base/at_exit.h"
     10 #include "base/command_line.h"
     11 #include "base/file_util.h"
     12 #include "base/path_service.h"
     13 #include "base/win/scoped_com_initializer.h"
     14 #include "base/win/shortcut.h"
     15 #include "cloud_print/common/win/cloud_print_utils.h"
     16 #include "cloud_print/common/win/install_utils.h"
     17 #include "cloud_print/resources.h"
     18 #include "cloud_print/service/service_constants.h"
     19 #include "cloud_print/service/service_switches.h"
     20 #include "cloud_print/service/win/service_controller.h"
     21 
     22 namespace {
     23 
     24 const wchar_t kConfigBinaryName[] = L"cloud_print_service_config.exe";
     25 
     26 base::FilePath GetShortcutPath(int dir_key, bool with_subdir) {
     27   base::FilePath path;
     28   if (!PathService::Get(dir_key, &path))
     29     return base::FilePath();
     30   path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME));
     31   if (with_subdir)
     32     path = path.Append(cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME));
     33   return path.InsertBeforeExtension(L".lnk");
     34 }
     35 
     36 void CreateShortcut(int dir_key, bool with_subdir,
     37                     base::win::ShortcutOperation operation) {
     38   base::FilePath path = GetShortcutPath(dir_key, with_subdir);
     39   if (path.empty())
     40     return;
     41   file_util::CreateDirectory(path.DirName());
     42   base::win::ShortcutProperties properties;
     43 
     44   base::FilePath exe_path;
     45   if (!PathService::Get(base::FILE_EXE, &exe_path))
     46     return;
     47   exe_path = exe_path.DirName().Append(base::FilePath(kConfigBinaryName));
     48   properties.set_target(exe_path);
     49   properties.set_working_dir(exe_path.DirName());
     50   CreateOrUpdateShortcutLink(path, properties, operation);
     51 }
     52 
     53 void CreateShortcuts(bool create_always) {
     54   base::win::ScopedCOMInitializer co_init;
     55   base::win::ShortcutOperation operation =
     56       create_always ? base::win::SHORTCUT_CREATE_ALWAYS :
     57                       base::win::SHORTCUT_REPLACE_EXISTING;
     58   CreateShortcut(base::DIR_COMMON_START_MENU, true, operation);
     59   CreateShortcut(base::DIR_COMMON_DESKTOP, false, operation);
     60 }
     61 
     62 void DeleteShortcut(int dir_key, bool with_subdir) {
     63   base::FilePath path = GetShortcutPath(dir_key, with_subdir);
     64   if (path.empty())
     65     return;
     66   if (with_subdir)
     67     base::DeleteFile(path.DirName(), true);
     68   else
     69     base::DeleteFile(path, false);
     70 }
     71 
     72 void DeleteShortcuts() {
     73   DeleteShortcut(base::DIR_COMMON_START_MENU, true);
     74   DeleteShortcut(base::DIR_COMMON_DESKTOP, false);
     75 }
     76 
     77 }  // namespace
     78 
     79 HRESULT ProcessInstallerSwitches() {
     80   const CommandLine& command_line(*CommandLine::ForCurrentProcess());
     81 
     82   if (command_line.HasSwitch(kInstallSwitch)) {
     83     base::FilePath old_location =
     84         cloud_print::GetInstallLocation(kGoogleUpdateId);
     85 
     86     cloud_print::CreateUninstallKey(
     87         kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME),
     88         kUninstallSwitch);
     89 
     90     ServiceController controller;
     91     HRESULT hr = controller.UpdateBinaryPath();
     92     if (FAILED(hr))
     93       return hr;
     94 
     95     if (!old_location.empty() &&
     96         cloud_print::IsProgramsFilesParent(old_location) &&
     97         old_location != cloud_print::GetInstallLocation(kGoogleUpdateId)) {
     98       base::DeleteFile(old_location, true);
     99     }
    100 
    101     cloud_print::SetGoogleUpdateKeys(
    102         kGoogleUpdateId, cloud_print::LoadLocalString(IDS_FULL_PRODUCT_NAME));
    103 
    104     CreateShortcuts(old_location.empty());
    105 
    106     return S_OK;
    107   } else if (command_line.HasSwitch(kUninstallSwitch)) {
    108     ServiceController controller;
    109     HRESULT hr = controller.UninstallService();
    110     if (FAILED(hr))
    111       return hr;
    112 
    113     DeleteShortcuts();
    114 
    115     cloud_print::DeleteGoogleUpdateKeys(kGoogleUpdateId);
    116     cloud_print::DeleteUninstallKey(kGoogleUpdateId);
    117     cloud_print::DeleteProgramDir(kDeleteSwitch);
    118     return S_OK;
    119   } else if (command_line.HasSwitch(kDeleteSwitch)) {
    120     base::FilePath delete_path = command_line.GetSwitchValuePath(kDeleteSwitch);
    121     if (!delete_path.empty() &&
    122         cloud_print::IsProgramsFilesParent(delete_path)) {
    123       base::DeleteFile(delete_path, true);
    124     }
    125     return S_OK;
    126   }
    127 
    128   return S_FALSE;
    129 }
    130 
    131 class CloudPrintServiceSetupModule
    132     : public ATL::CAtlExeModuleT<CloudPrintServiceSetupModule> {
    133 };
    134 
    135 CloudPrintServiceSetupModule _AtlModule;
    136 
    137 int WINAPI WinMain(__in  HINSTANCE hInstance,
    138                    __in  HINSTANCE hPrevInstance,
    139                    __in  LPSTR lpCmdLine,
    140                    __in  int nCmdShow) {
    141   base::AtExitManager at_exit;
    142   CommandLine::Init(0, NULL);
    143   return ProcessInstallerSwitches();
    144 }
    145