ReactOS 0.4.16-dev-889-g9563c07
getenv.cpp
Go to the documentation of this file.
1//
2// getenv.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Defines the getenv family of functions, which search the environment for a
7// variable and return its value.
8//
10#include <stdlib.h>
11#include <string.h>
12
13
14
15//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16//
17// getenv() and _wgetenv()
18//
19//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20// These functions search the environment for a variable with the given name.
21// If such a variable is found, a pointer to its value is returned. Otherwise,
22// nullptr is returned. Note that if the environment is access and manipulated
23// from multiple threads, this function cannot be safely used: the returned
24// pointer may not be valid when the function returns.
25template <typename Character>
26static Character* __cdecl common_getenv_nolock(Character const* const name) throw()
27{
28 typedef __crt_char_traits<Character> traits;
29
30 Character** const environment = traits::get_or_create_environment_nolock();
31 if (environment == nullptr || name == nullptr)
32 return nullptr;
33
34 size_t const name_length = traits::tcslen(name);
35
36 for (Character** current = environment; *current; ++current)
37 {
38 if (traits::tcslen(*current) <= name_length)
39 continue;
40
41 if (*(*current + name_length) != '=')
42 continue;
43
44 if (traits::tcsnicoll(*current, name, name_length) != 0)
45 continue;
46
47 // Internal consistency check: The environment string should never use
48 // a bigger buffer than _MAX_ENV. See also the SetEnvironmentVariable
49 // SDK function.
50 _ASSERTE(traits::tcsnlen(*current + name_length + 1, _MAX_ENV) < _MAX_ENV);
51
52 return *current + name_length + 1;
53 }
54
55 return nullptr;
56}
57
58
59
60template <typename Character>
61static Character* __cdecl common_getenv(Character const* const name) throw()
62{
63 typedef __crt_char_traits<Character> traits;
64
65 _VALIDATE_RETURN(name != nullptr, EINVAL, nullptr);
66 _VALIDATE_RETURN(traits::tcsnlen(name, _MAX_ENV) < _MAX_ENV, EINVAL, nullptr);
67
68 Character* result = 0;
69
71 __try
72 {
74 }
76 {
78 }
80
81 return result;
82}
83
84extern "C" char* __cdecl getenv(char const* const name)
85{
86 return common_getenv(name);
87}
88
89extern "C" wchar_t* __cdecl _wgetenv(wchar_t const* const name)
90{
91 return common_getenv(name);
92}
93
94
95
96//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97//
98// getenv_s() and _wgetenv_s()
99//
100//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101// These functions search the environment for a variable with the given name.
102// If such a variable is found, its value is copied into the provided buffer.
103// The number of characters in the value (including the null terminator) is
104// stored in '*required_count'. Returns 0 on success; returns ERANGE if the
105// provided buffer is too small; otherwise returns an error code on failure.
106template <typename Character>
107_Success_(return == 0)
108static errno_t __cdecl common_getenv_s_nolock(
109 size_t* const required_count,
112 Character const* const name
114{
115 typedef __crt_char_traits<Character> traits;
116
117 _VALIDATE_RETURN_ERRCODE(required_count != nullptr, EINVAL);
118 *required_count = 0;
119
121 (buffer != nullptr && buffer_count > 0) ||
122 (buffer == nullptr && buffer_count == 0), EINVAL);
123
124 if (buffer)
125 buffer[0] = '\0';
126
127 Character const* const value = common_getenv_nolock(name);
128 if (!value)
129 return 0;
130
131 *required_count = traits::tcslen(value) + 1;
132 if (buffer_count == 0)
133 return 0;
134
135 // The buffer is too small; we return an error code and the caller can have
136 // the opportunity to try again with a larger buffer:
137 if (*required_count > buffer_count)
138 return ERANGE;
139
140 _ERRCHECK(traits::tcscpy_s(buffer, buffer_count, value));
141 return 0;
142}
143
144template <typename Character>
145_Success_(return == 0)
146static errno_t __cdecl common_getenv_s(
147 size_t* const required_count,
149 size_t const buffer_count,
150 Character const* const name
151 ) throw()
152{
153 errno_t status = 0;
154
156 __try
157 {
158 status = common_getenv_s_nolock(required_count, buffer, buffer_count, name);
159 }
161 {
163 }
165
166 return status;
167}
168
170 size_t* const required_count,
171 char* const buffer,
172 size_t const buffer_count,
173 char const* const name
174 )
175{
176 return common_getenv_s(required_count, buffer, buffer_count, name);
177}
178
180 size_t* const required_count,
181 wchar_t* const buffer,
182 size_t const buffer_count,
183 wchar_t const* const name
184 )
185{
186 return common_getenv_s(required_count, buffer, buffer_count, name);
187}
188
189
190
191//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
192//
193// _dupenv_s() and _wdupenv_s()
194//
195//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
196// These functions search the environment for a variable with the given name.
197// If a variable is found, a buffer is allocated using the public malloc to hold
198// the value of the variable. The value is copied into the buffer and the buffer
199// is returned to the caller via 'buffer_pointer' and 'buffer_count'. The caller
200// is responsible for freeing the buffer.
201//
202// Returns zero on success; returns an error code on failure. Note that if a
203// variable with the specified name is not found, that is still considered a
204// success; in this case, the 'value' is an empty string ('*buffer_count' will
205// be zero and '*buffer_pointer' will be nullptr).
206template <typename Character>
209 _Out_opt_ size_t* const buffer_count,
210 Character const* const name,
211 int const block_use,
212 char const* const file_name,
213 int const line_number
214 ) throw()
215{
216 // These are referenced only in the Debug CRT build
220
221 typedef __crt_char_traits<Character> traits;
222
223 _VALIDATE_RETURN_ERRCODE(buffer_pointer != nullptr, EINVAL);
224 *buffer_pointer = nullptr;
225
226 if (buffer_count != nullptr)
227 *buffer_count = 0;
228
230
231 Character const* const value = common_getenv_nolock(name);
232 if (value == nullptr)
233 return 0;
234
235 size_t const value_count = traits::tcslen(value) + 1;
236
237 *buffer_pointer = static_cast<Character*>(_calloc_dbg(
238 value_count,
239 sizeof(Character),
240 block_use,
241 file_name,
242 line_number));
243 _VALIDATE_RETURN_ERRCODE_NOEXC(*buffer_pointer != nullptr, ENOMEM);
244
245 _ERRCHECK(traits::tcscpy_s(*buffer_pointer, value_count, value));
246 if (buffer_count != nullptr)
247 *buffer_count = value_count;
248
249 return 0;
250}
251
252template <typename Character>
253_Success_(return != 0)
254static errno_t __cdecl common_dupenv_s(
257 Character const* const name,
261 ) throw()
262{
263 errno_t status = 0;
264
266 __try
267 {
269 buffer_pointer,
271 name,
272 block_use,
273 file_name,
275 }
277 {
279 }
281
282 return status;
283}
284
286 char** const buffer_pointer,
287 size_t* const buffer_count,
288 char const* const name
289 )
290{
291 return common_dupenv_s(buffer_pointer, buffer_count, name, _NORMAL_BLOCK, nullptr, 0);
292}
293
295 wchar_t** const buffer_pointer,
296 size_t* const buffer_count,
297 wchar_t const* const name
298 )
299{
300 return common_dupenv_s(buffer_pointer, buffer_count, name, _NORMAL_BLOCK, nullptr, 0);
301}
302
303#ifdef _DEBUG
304
305#undef _dupenv_s_dbg
306#undef _wdupenv_s_dbg
307
308extern "C" errno_t __cdecl _dupenv_s_dbg(
309 char** const buffer_pointer,
310 size_t* const buffer_count,
311 char const* const name,
312 int const block_use,
313 char const* const file_name,
314 int const line_number
315 )
316{
317 return common_dupenv_s(buffer_pointer, buffer_count, name, block_use, file_name, line_number);
318}
319
321 wchar_t** const buffer_pointer,
322 size_t* const buffer_count,
323 wchar_t const* const name,
324 int const block_use,
325 char const* const file_name,
326 int const line_number
327 )
328{
329 return common_dupenv_s(buffer_pointer, buffer_count, name, block_use, file_name, line_number);
330}
331
332#endif // _DEBUG
#define EINVAL
Definition: acclib.h:90
#define ENOMEM
Definition: acclib.h:84
#define ERANGE
Definition: acclib.h:92
#define __cdecl
Definition: accygwin.h:79
void __cdecl __acrt_unlock(_In_ __acrt_lock_id lock)
Definition: locks.cpp:57
@ __acrt_environment_lock
#define _ERRCHECK(e)
#define _VALIDATE_RETURN(expr, errorcode, retexpr)
#define _ASSERTE(expr)
Definition: crtdbg.h:114
#define _NORMAL_BLOCK
Definition: crtdbg.h:67
#define _calloc_dbg(c, s, t, f, l)
Definition: crtdbg.h:205
__acrt_lock(__acrt_heap_lock)
int const char const *const int const line_number
Definition: debug_heap.cpp:499
errno_t __cdecl _wgetenv_s(size_t *const required_count, wchar_t *const buffer, size_t const buffer_count, wchar_t const *const name)
Definition: getenv.cpp:179
errno_t __cdecl getenv_s(size_t *const required_count, char *const buffer, size_t const buffer_count, char const *const name)
Definition: getenv.cpp:169
_Out_opt_ size_t *const Character const *const int const char const *const file_name
Definition: getenv.cpp:259
errno_t __cdecl _wdupenv_s(wchar_t **const buffer_pointer, size_t *const buffer_count, wchar_t const *const name)
Definition: getenv.cpp:294
errno_t __cdecl _dupenv_s(char **const buffer_pointer, size_t *const buffer_count, char const *const name)
Definition: getenv.cpp:285
_Out_opt_ size_t *const Character const *const int const block_use
Definition: getenv.cpp:258
static Character *__cdecl common_getenv(Character const *const name)
Definition: getenv.cpp:61
static Character *__cdecl common_getenv_nolock(Character const *const name)
Definition: getenv.cpp:26
char *__cdecl getenv(char const *const name)
Definition: getenv.cpp:84
size_t const buffer_count
Definition: getenv.cpp:111
static errno_t __cdecl common_dupenv_s_nolock(_Outptr_result_buffer_maybenull_(*buffer_count) _Outptr_result_maybenull_z_ Character **const buffer_pointer, _Out_opt_ size_t *const buffer_count, Character const *const name, int const block_use, char const *const file_name, int const line_number)
Definition: getenv.cpp:207
size_t const Character const *const name throw()
Definition: getenv.cpp:113
wchar_t *__cdecl _wgetenv(wchar_t const *const name)
Definition: getenv.cpp:89
GLuint buffer
Definition: glext.h:5915
GLuint64EXT * result
Definition: glext.h:11304
#define _MAX_ENV
Definition: stdlib.h:118
#define _VALIDATE_RETURN_ERRCODE(expr, errorcode)
#define _VALIDATE_RETURN_ERRCODE_NOEXC(expr, errorcode)
struct task_struct * current
Definition: linux.c:32
#define _Outptr_result_buffer_maybenull_(size)
Definition: ms_sal.h:464
#define _Out_writes_z_(s)
Definition: no_sal2.h:180
#define _Out_opt_
Definition: no_sal2.h:214
#define _Success_(c)
Definition: no_sal2.h:84
#define _Outptr_result_maybenull_z_
Definition: no_sal2.h:274
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:325
#define __try
Definition: pseh2_64.h:188
#define __endtry
Definition: pseh2_64.h:191
#define __finally
Definition: pseh2_64.h:190
Definition: name.c:39
Definition: ps.c:97
int errno_t
Definition: corecrt.h:615
#define _dupenv_s_dbg(ps1, size, s2, t, f, l)
Definition: crtdbg.h:270
#define _wdupenv_s_dbg(ps1, size, s2, t, f, l)
Definition: crtdbg.h:279
Definition: pdh_main.c:96
#define const
Definition: zconf.h:233