ReactOS 0.4.16-dev-852-gcfcc8d8
putenv.cpp File Reference
#include <corecrt_internal.h>
#include <corecrt_internal_traits.h>
#include <stdlib.h>
#include <string.h>
Include dependency graph for putenv.cpp:

Go to the source code of this file.

Functions

static bool other_environment_exists (wchar_t) throw ()
 
static bool other_environment_exists (char) throw ()
 
template<typename Character >
static size_t compute_required_transform_buffer_count (Character const *const name, Character const *const value) throw ()
 
template<typename Character >
static Character * create_environment_string (Character const *const name, Character const *const value) throw ()
 
template<typename Character >
static bool __cdecl set_variable_in_other_environment (Character const *const name, Character const *const value) throw ()
 
template<typename Character >
static int __cdecl common_putenv_nolock (Character const *const name, Character const *const value) throw ()
 
template<typename Character >
static int __cdecl common_putenv (Character const *const name, Character const *const value) throw ()
 
int __cdecl _putenv (char const *const option)
 
int __cdecl _wputenv (wchar_t const *const option)
 
errno_t __cdecl _putenv_s (char const *const name, char const *const value)
 
errno_t __cdecl _wputenv_s (wchar_t const *const name, wchar_t const *const value)
 

Function Documentation

◆ _putenv()

int __cdecl _putenv ( char const *const  option)

Definition at line 222 of file putenv.cpp.

223{
224 return common_putenv(option, static_cast<char const*>(nullptr));
225}
static int __cdecl common_putenv(Character const *const name, Character const *const value)
Definition: putenv.cpp:199
Definition: getopt.h:109
#define const
Definition: zconf.h:233

◆ _putenv_s()

errno_t __cdecl _putenv_s ( char const *const  name,
char const *const  value 
)

Definition at line 234 of file putenv.cpp.

235{
237 return common_putenv(name, value) == 0 ? 0 : errno;
238}
#define EINVAL
Definition: acclib.h:90
#define _VALIDATE_RETURN_ERRCODE(expr, errorcode)
#define errno
Definition: errno.h:18
Definition: name.c:39
Definition: pdh_main.c:96

◆ _wputenv()

int __cdecl _wputenv ( wchar_t const *const  option)

Definition at line 227 of file putenv.cpp.

228{
229 return common_putenv(option, static_cast<wchar_t const*>(nullptr));
230}

◆ _wputenv_s()

errno_t __cdecl _wputenv_s ( wchar_t const *const  name,
wchar_t const *const  value 
)

Definition at line 240 of file putenv.cpp.

241{
243 return common_putenv(name, value) == 0 ? 0 : errno;
244}

◆ common_putenv()

template<typename Character >
static int __cdecl common_putenv ( Character const *const  name,
Character const *const  value 
)
throw (
)
static

Definition at line 199 of file putenv.cpp.

203{
204 int status = 0;
205
207 __try
208 {
210 }
212 {
214 }
216
217 return status;
218}
void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock)
Definition: locks.cpp:57
@ __acrt_environment_lock
__acrt_lock(__acrt_heap_lock)
#define __try
Definition: pseh2_64.h:172
#define __endtry
Definition: pseh2_64.h:175
#define __finally
Definition: pseh2_64.h:174
static int __cdecl common_putenv_nolock(Character const *const name, Character const *const value)
Definition: putenv.cpp:161
Definition: ps.c:97

Referenced by _putenv(), _putenv_s(), _wputenv(), and _wputenv_s().

◆ common_putenv_nolock()

template<typename Character >
static int __cdecl common_putenv_nolock ( Character const *const  name,
Character const *const  value 
)
throw (
)
static

Definition at line 161 of file putenv.cpp.

165{
166 typedef __crt_char_traits<Character> traits;
167
168 // Ensure that the environment is initialized:
169 if (!_environ_table.value() && !_wenviron_table.value())
170 return -1;
171
172 // At startup, we obtain the "native" flavor of environment strings from the
173 // operating system. So, a "main" program has _environ set and a "wmain"
174 // program has _wenviron set. Only when the user gets or puts the "other"
175 // flavor do we convert it.
176 _VALIDATE_RETURN(name != nullptr, EINVAL, -1);
177
178 __crt_unique_heap_ptr<Character> new_option(create_environment_string(name, value));
179 if (!new_option)
180 return -1;
181
182 if (traits::set_variable_in_environment_nolock(new_option.detach(), 1) != 0)
183 return -1;
184
185 // See if the "other" environment type exists; if it doesn't, we're done.
186 // Otherwise, put the new option into the other environment as well.
187 if (!other_environment_exists(Character()))
188 return 0;
189
191 return -1;
192
193 return 0;
194}
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
__crt_state_management::dual_state_global< wchar_t ** > _wenviron_table
__crt_state_management::dual_state_global< char ** > _environ_table
static bool __cdecl set_variable_in_other_environment(Character const *const name, Character const *const value)
Definition: putenv.cpp:107
static Character * create_environment_string(Character const *const name, Character const *const value)
Definition: putenv.cpp:52
static bool other_environment_exists(wchar_t)
Definition: putenv.cpp:17

Referenced by common_putenv().

◆ compute_required_transform_buffer_count()

template<typename Character >
static size_t compute_required_transform_buffer_count ( Character const *const  name,
Character const *const  value 
)
throw (
)
static

Definition at line 25 of file putenv.cpp.

29{
30 // Compute the amount of space required for the transformation:
31 size_t const name_count_required = __crt_compute_required_transform_buffer_count(CP_ACP, name);
32 _VALIDATE_RETURN_NOEXC(name_count_required != 0, EILSEQ, false);
33
34 if (!value)
35 return name_count_required;
36
37 size_t const value_count_required = __crt_compute_required_transform_buffer_count(CP_ACP, value);
38 _VALIDATE_RETURN_NOEXC(value_count_required != 0, EILSEQ, false);
39
40 // Note that each count includes space a the null terminator. Since we'll
41 // only be storing one terminator in the buffer, the space for the other
42 // terminator will be used to store the '=' between the name and the value.
43 return name_count_required + value_count_required;
44}
size_t __crt_compute_required_transform_buffer_count(unsigned const code_page, _In_z_ char const *const string)
#define CP_ACP
Definition: compat.h:109
#define _VALIDATE_RETURN_NOEXC(expr, errorcode, retexpr)
#define EILSEQ
Definition: errno.h:109

Referenced by set_variable_in_other_environment().

◆ create_environment_string()

template<typename Character >
static Character * create_environment_string ( Character const *const  name,
Character const *const  value 
)
throw (
)
static

Definition at line 52 of file putenv.cpp.

56{
57 typedef __crt_char_traits<Character> traits;
58
59 if (value)
60 {
61 size_t const name_length = traits::tcsnlen(name, _MAX_ENV);
62 size_t const value_length = traits::tcsnlen(value, _MAX_ENV);
63
64 _VALIDATE_RETURN(name_length < _MAX_ENV, EINVAL, nullptr);
65 _VALIDATE_RETURN(value_length < _MAX_ENV, EINVAL, nullptr);
66
67 // We add two to the length: one for the '=' and one for the terminator
68 size_t const buffer_count = name_length + 1 + value_length + 1;
69
70 __crt_unique_heap_ptr<Character> buffer(_calloc_crt_t(Character, buffer_count));
71 if (!buffer)
72 return nullptr;
73
74 traits::tcscpy_s(buffer.get(), buffer_count, name);
75 buffer.get()[name_length] = '=';
76 traits::tcscpy_s(buffer.get() + name_length + 1, value_length + 1, value);
77
78 return buffer.detach();
79 }
80 else
81 {
82 Character const* const equal_sign_it = traits::tcschr(name, '=');
83 if (equal_sign_it)
84 {
85 // Validate the length of both the name and the value:
86 _VALIDATE_RETURN(equal_sign_it - name < _MAX_ENV, EINVAL, nullptr);
87 _VALIDATE_RETURN(traits::tcsnlen(equal_sign_it + 1, _MAX_ENV) < _MAX_ENV, EINVAL, nullptr);
88 }
89
90 size_t const buffer_count = traits::tcslen(name) + 1;
91
92 __crt_unique_heap_ptr<Character> buffer(_calloc_crt_t(Character, buffer_count));
93 if (!buffer)
94 return nullptr;
95
96 traits::tcscpy_s(buffer.get(), buffer_count, name);
97
98 return buffer.detach();
99 }
100}
GLuint buffer
Definition: glext.h:5915
#define _MAX_ENV
Definition: stdlib.h:118
size_t const buffer_count
Definition: xtoa.cpp:36

Referenced by common_putenv_nolock().

◆ other_environment_exists() [1/2]

static bool other_environment_exists ( char  )
throw (
)
static

Definition at line 18 of file putenv.cpp.

18{ return _wenviron_table.value() != nullptr; }

◆ other_environment_exists() [2/2]

static bool other_environment_exists ( wchar_t  )
throw (
)
static

Definition at line 17 of file putenv.cpp.

17{ return _environ_table.value() != nullptr; }

Referenced by common_putenv_nolock().

◆ set_variable_in_other_environment()

template<typename Character >
static bool __cdecl set_variable_in_other_environment ( Character const *const  name,
Character const *const  value 
)
throw (
)
static

Definition at line 107 of file putenv.cpp.

111{
112 typedef __crt_char_traits<Character> traits;
113 typedef typename traits::other_char_type other_char_type;
114 typedef __crt_char_traits<other_char_type> other_traits;
115
117
118 __crt_unique_heap_ptr<other_char_type> buffer(_calloc_crt_t(other_char_type, buffer_count));
119 if (!buffer)
120 return false;
121
122 size_t const name_written_count = __crt_transform_string(CP_ACP, name, buffer.get(), buffer_count);
123 _VALIDATE_RETURN_NOEXC(name_written_count != 0, EILSEQ, false);
124
125 if (value)
126 {
127 // Overwrite the null terminator with an '=':
128 buffer.get()[name_written_count - 1] = '=';
129
130 size_t const value_written_count = __crt_transform_string(
131 CP_ACP,
132 value,
133 buffer.get() + name_written_count,
134 buffer_count - name_written_count);
135 _VALIDATE_RETURN_NOEXC(value_written_count != 0, EILSEQ, false);
136 }
137
138 return other_traits::set_variable_in_environment_nolock(buffer.detach(), 0) == 0;
139}
static size_t compute_required_transform_buffer_count(Character const *const name, Character const *const value)
Definition: putenv.cpp:25

Referenced by common_putenv_nolock().