1 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
2 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
3 // Copyright (c) 2009 Boris Schaeling
4 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
5 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
6 // Copyright (c) 2016 Hartmut Kaiser
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 
11 #ifndef HPX_PROCESS_WINDOWS_INITIALIZERS_SET_ENV_HPP
12 #define HPX_PROCESS_WINDOWS_INITIALIZERS_SET_ENV_HPP
13 
14 #include <hpx/config.hpp>
15 
16 #if defined(HPX_WINDOWS)
17 #include <hpx/components/process/util/windows/initializers/initializer_base.hpp>
18 #include <hpx/runtime/serialization/string.hpp>
19 
20 #include <boost/range/numeric.hpp>
21 
22 #include <cstddef>
23 #include <cstring>
24 #include <iterator>
25 #include <numeric>
26 #include <vector>
27 #include <windows.h>
28 
29 namespace hpx { namespace components { namespace process { namespace windows {
30 
31 namespace initializers {
32 
33 template <class Range, bool Unicode>
34 class set_env_ : public initializer_base
35 {
36 private:
37     typedef typename Range::value_type String;
38     typedef typename String::value_type Char;
39 
get_size(std::size_t len,String const & s)40     static std::size_t get_size(std::size_t len, String const& s)
41     {
42         return len + s.size() + 1;
43     }
44 
45     struct copy_env
46     {
copy_envhpx::components::process::windows::initializers::set_env_::copy_env47         copy_env(Char* curr)
48           : curr_(curr)
49         {}
50 
operator ()hpx::components::process::windows::initializers::set_env_::copy_env51         void operator()(String const& s)
52         {
53             std::memcpy(curr_, s.c_str(), s.size());
54             curr_ += s.size();
55             *curr_++ = 0;
56         }
57 
58         Char* curr_;
59     };
60 
61 public:
set_env_()62     set_env_()
63     {
64         env_.resize(1);
65         env_[0] = 0;
66     }
67 
set_env_(const Range & envs)68     set_env_(const Range &envs)
69     {
70         std::size_t s = std::accumulate(envs.begin(), envs.end(),
71             std::size_t(0), &set_env_::get_size);
72 
73         env_.resize(s + 1);
74         std::for_each(envs.begin(), envs.end(), copy_env(env_.data()));
75         env_[env_.size() - 1] = 0;
76     }
77 
78     template <class WindowsExecutor>
on_CreateProcess_setup(WindowsExecutor & e) const79     void on_CreateProcess_setup(WindowsExecutor &e) const
80     {
81         e.env = LPVOID(env_.data());
82         if (Unicode)
83             e.creation_flags |= CREATE_UNICODE_ENVIRONMENT;
84     }
85 
86 private:
87     friend class hpx::serialization::access;
88 
89     template <typename Archive>
serialize(Archive & ar,unsigned const)90     void serialize(Archive& ar, unsigned const)
91     {
92         ar & env_;
93     }
94 
95     std::vector<Char> env_;
96 };
97 
98 #if defined(_UNICODE) || defined(UNICODE)
99 template <class Range>
set_env(const Range & envs)100 set_env_<Range, true> set_env(const Range &envs)
101 {
102     return set_env_<Range, true>(envs);
103 }
104 #else
105 template <class Range>
set_env(const Range & envs)106 set_env_<Range, false> set_env(const Range &envs)
107 {
108     return set_env_<Range, false>(envs);
109 }
110 #endif
111 
112 }
113 
114 }}}}
115 
116 #endif
117 #endif
118