aboutsummaryrefslogtreecommitdiff
path: root/src/daemonizer/windows_daemonizer.inl
blob: 5091ca9484197b780693f2d5a03331967506134a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#pragma once

#include "common/util.h"
#include "daemonizer/windows_service.h"
#include "daemonizer/windows_service_runner.h"

#include <shlobj.h>
#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp>

namespace daemonizer
{
  namespace
  {
    const command_line::arg_descriptor<bool> arg_install_service = {
      "install-service"
    , "Install Windows service"
    };
    const command_line::arg_descriptor<bool> arg_uninstall_service = {
      "uninstall-service"
    , "Uninstall Windows service"
    };
    const command_line::arg_descriptor<bool> arg_start_service = {
      "start-service"
    , "Start Windows service"
    };
    const command_line::arg_descriptor<bool> arg_stop_service = {
      "stop-service"
    , "Stop Windows service"
    };
    const command_line::arg_descriptor<bool> arg_is_service = {
      "run-as-service"
    , "Hidden -- true if running as windows service"
    };

    std::string get_argument_string(int argc, char const * argv[])
    {
      std::string result = "";
      for (int i = 1; i < argc; ++i)
      {
        result += " " + std::string{argv[i]};
      }
      return result;
    }
  }

  inline void init_options(
      boost::program_options::options_description & hidden_options
    , boost::program_options::options_description & normal_options
    )
  {
    command_line::add_arg(normal_options, arg_install_service);
    command_line::add_arg(normal_options, arg_uninstall_service);
    command_line::add_arg(normal_options, arg_start_service);
    command_line::add_arg(normal_options, arg_stop_service);
    command_line::add_arg(hidden_options, arg_is_service);
  }

  inline boost::filesystem::path get_default_data_dir()
  {
    bool admin;
    if (!windows::check_admin(admin))
    {
      admin = false;
    }
    if (admin)
    {
      return boost::filesystem::absolute(
          tools::get_special_folder_path(CSIDL_COMMON_APPDATA, true) + "\\" + CRYPTONOTE_NAME
        );
    }
    else
    {
      return boost::filesystem::absolute(
          tools::get_special_folder_path(CSIDL_APPDATA, true) + "\\" + CRYPTONOTE_NAME
        );
    }
  }

  inline boost::filesystem::path get_relative_path_base(
      boost::program_options::variables_map const & vm
    )
  {
    if (command_line::has_arg(vm, arg_is_service))
    {
      if (command_line::has_arg(vm, command_line::arg_data_dir))
      {
        return command_line::get_arg(vm, command_line::arg_data_dir);
      }
      else
      {
        return tools::get_default_data_dir();
      }
    }
    else
    {
      return boost::filesystem::current_path();
    }
  }

  template <typename T_executor>
  inline bool daemonize(
      int argc, char const * argv[]
    , T_executor && executor // universal ref
    , boost::program_options::variables_map const & vm
    )
  {
    std::string arguments = get_argument_string(argc, argv);

    if (command_line::arg_present(vm, arg_is_service))
    {
      // TODO - Set the service status here for return codes
      windows::t_service_runner<typename T_executor::t_daemon>::run(
        executor.name()
      , executor.create_daemon(vm)
      );
      return true;
    }
    else if (command_line::arg_present(vm, arg_install_service))
    {
      if (windows::ensure_admin(arguments))
      {
        arguments += " --run-as-service";
        return windows::install_service(executor.name(), arguments);
      }
    }
    else if (command_line::arg_present(vm, arg_uninstall_service))
    {
      if (windows::ensure_admin(arguments))
      {
        return windows::uninstall_service(executor.name());
      }
    }
    else if (command_line::arg_present(vm, arg_start_service))
    {
      if (windows::ensure_admin(arguments))
      {
        return windows::start_service(executor.name());
      }
    }
    else if (command_line::arg_present(vm, arg_stop_service))
    {
      if (windows::ensure_admin(arguments))
      {
        return windows::stop_service(executor.name());
      }
    }
    else // interactive
    {
      //LOG_PRINT_L0(CRYPTONOTE_NAME << " v" << MONERO_VERSION_FULL);
      return executor.run_interactive(vm);
    }

    return false;
  }
}