ReactOS 0.4.16-dev-1020-gf135cab
cenvarg.cpp File Reference
#include <corecrt_internal.h>
#include <errno.h>
#include <corecrt_internal_traits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Include dependency graph for cenvarg.cpp:

Go to the source code of this file.

Functions

template<typename Character >
static errno_t __cdecl construct_command_line (Character const *const *const argv, Character **const command_line_result) throw ()
 
template<typename Character >
static errno_t __cdecl construct_environment_block (_In_opt_z_ Character const *const *const envp, _Outptr_result_maybenull_ Character **const environment_block_result) throw ()
 
template<typename Character >
 _Success_ (return==0) _Ret_range_(-1
 
static int __cdecl common_pack_argv_and_envp (_In_z_ Character const *const *const argv, _In_opt_z_ Character const *const *const envp, _Outptr_result_maybenull_ Character **const command_line_result, _Outptr_result_maybenull_ Character **const environment_block_result) throw ()
 
int __cdecl __acrt_pack_narrow_command_line_and_environment (char const *const *const argv, char const *const *const envp, char **const command_line_result, char **const environment_block_result)
 
int __cdecl __acrt_pack_wide_command_line_and_environment (wchar_t const *const *const argv, wchar_t const *const *const envp, wchar_t **const command_line_result, wchar_t **const environment_block_result)
 
template<typename Character >
 _Success_ (return !=0) static Character **__cdecl common_capture_argv(_In_ va_list *const arglist
 
_In_z_ Character const *const _When_ (return==caller_array, _Post_z_) _Out_writes_(caller_array_count) Character **const caller_array
 
_In_z_ Character const *const _In_ size_t const caller_array_count throw ()
 
char ** __acrt_capture_narrow_argv (va_list *const arglist, char const *const first_argument, char **const caller_array, size_t const caller_array_count)
 
wchar_t ** __acrt_capture_wide_argv (va_list *const arglist, wchar_t const *const first_argument, wchar_t **const caller_array, size_t const caller_array_count)
 

Variables

_In_z_ Character const *const first_argument
 

Function Documentation

◆ __acrt_capture_narrow_argv()

char ** __acrt_capture_narrow_argv ( va_list *const  arglist,
char const *const  first_argument,
char **const  caller_array,
size_t const  caller_array_count 
)

Definition at line 351 of file cenvarg.cpp.

357{
358 return common_capture_argv(arglist, first_argument, caller_array, caller_array_count);
359}
_In_z_ Character const *const first_argument
Definition: cenvarg.cpp:289
_Ret_z_ _In_z_ char const _In_ size_t caller_array_count
va_lists_t arglist[FMT_ARGMAX+1]
Definition: format.c:284

◆ __acrt_capture_wide_argv()

wchar_t ** __acrt_capture_wide_argv ( va_list *const  arglist,
wchar_t const *const  first_argument,
wchar_t **const  caller_array,
size_t const  caller_array_count 
)

Definition at line 361 of file cenvarg.cpp.

367{
368 return common_capture_argv(arglist, first_argument, caller_array, caller_array_count);
369}

◆ __acrt_pack_narrow_command_line_and_environment()

int __cdecl __acrt_pack_narrow_command_line_and_environment ( char const *const *const  argv,
char const *const *const  envp,
char **const  command_line_result,
char **const  environment_block_result 
)

Definition at line 257 of file cenvarg.cpp.

263{
264 return common_pack_argv_and_envp(argv, envp, command_line_result, environment_block_result);
265}
static int __cdecl common_pack_argv_and_envp(_In_z_ Character const *const *const argv, _In_opt_z_ Character const *const *const envp, _Outptr_result_maybenull_ Character **const command_line_result, _Outptr_result_maybenull_ Character **const environment_block_result)
Definition: cenvarg.cpp:235
#define argv
Definition: mplay32.c:18

◆ __acrt_pack_wide_command_line_and_environment()

int __cdecl __acrt_pack_wide_command_line_and_environment ( wchar_t const *const *const  argv,
wchar_t const *const *const  envp,
wchar_t **const  command_line_result,
wchar_t **const  environment_block_result 
)

Definition at line 267 of file cenvarg.cpp.

273{
274 return common_pack_argv_and_envp(argv, envp, command_line_result, environment_block_result);
275}

◆ _Success_() [1/2]

template<typename Character >
_Success_ ( return = 0) const

◆ _Success_() [2/2]

template<typename Character >
_Success_ ( return  = = 0)

◆ _When_()

_In_z_ Character const *const _When_ ( return  = = caller_array,
_Post_z_   
) const

◆ common_pack_argv_and_envp()

static int __cdecl common_pack_argv_and_envp ( _In_z_ Character const *const *const  argv,
_In_opt_z_ Character const *const *const  envp,
_Outptr_result_maybenull_ Character **const  command_line_result,
_Outptr_result_maybenull_ Character **const  environment_block_result 
)
throw (
)
static

Definition at line 235 of file cenvarg.cpp.

241{
242 typedef __crt_char_traits<Character> traits;
243
244 __crt_unique_heap_ptr<Character> command_line;
245 if (construct_command_line(argv, command_line.get_address_of()) != 0)
246 return -1;
247
248 __crt_unique_heap_ptr<Character> environment_block;
249 if (construct_environment_block(envp, environment_block.get_address_of()) != 0)
250 return -1;
251
252 *command_line_result = command_line.detach();
253 *environment_block_result = environment_block.detach();
254 return 0;
255}
static errno_t __cdecl construct_command_line(Character const *const *const argv, Character **const command_line_result)
Definition: cenvarg.cpp:24
static errno_t __cdecl construct_environment_block(_In_opt_z_ Character const *const *const envp, _Outptr_result_maybenull_ Character **const environment_block_result)
Definition: cenvarg.cpp:85

Referenced by __acrt_pack_narrow_command_line_and_environment(), and __acrt_pack_wide_command_line_and_environment().

◆ construct_command_line()

template<typename Character >
static errno_t __cdecl construct_command_line ( Character const *const *const  argv,
Character **const  command_line_result 
)
throw (
)
static

Definition at line 24 of file cenvarg.cpp.

28{
29 typedef __crt_char_traits<Character> traits;
30
31 *command_line_result = nullptr;
32
33 // Compute the number of bytes required to store the arguments in argv in a
34 // command line string (including spaces between arguments and a terminator):
35 size_t const command_line_count = [&]
36 {
37 size_t n = 0;
38 for (Character const* const* it = argv; *it; n += traits::tcslen(*it++) + 1) { }
39
40 // If there were no arguments, return 1 so that we can return an empty
41 // string:
42 return __max(n, 1);
43 }();
44
45 __crt_unique_heap_ptr<Character> command_line(_calloc_crt_t(Character, command_line_count));
46 if (!command_line)
47 {
49 return errno = ENOMEM;
50 }
51
52 Character const* const* source_it = argv;
53 Character* result_it = command_line.get();
54
55 // If there are no arguments, just return the empty string:
56 if (*source_it == nullptr)
57 {
58 *command_line_result = command_line.detach();
59 return 0;
60 }
61
62 // Copy the arguments, separated by spaces:
63 while (*source_it != nullptr)
64 {
65 _ERRCHECK(traits::tcscpy_s(result_it, command_line_count - (result_it - command_line.get()), *source_it));
66 result_it += traits::tcslen(*source_it);
67 *result_it++ = ' ';
68 ++source_it;
69 }
70
71 // Replace the last space with a terminator:
72 result_it[-1] = '\0';
73
74 *command_line_result = command_line.detach();
75 return 0;
76}
#define ENOMEM
Definition: acclib.h:84
#define _ERRCHECK(e)
void __cdecl __acrt_errno_map_os_error(unsigned long)
Definition: errno.cpp:91
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
GLdouble n
Definition: glext.h:7729
#define __max(a, b)
Definition: stdlib.h:101
#define errno
Definition: errno.h:18

Referenced by common_pack_argv_and_envp().

◆ construct_environment_block()

template<typename Character >
static errno_t __cdecl construct_environment_block ( _In_opt_z_ Character const *const *const  envp,
_Outptr_result_maybenull_ Character **const  environment_block_result 
)
throw (
)
static

Definition at line 85 of file cenvarg.cpp.

89{
90 typedef __crt_char_traits<Character> traits;
91
92 *environment_block_result = nullptr;
93
94 // If envp is null, we will use the current environment of this process as
95 // the environment for the new process. No action is required in this case
96 // because simply passing a null environment pointer to CreateProcess will
97 // do the right thing.
98 if (envp == nullptr)
99 return 0;
100
101 // Get the value of the SystemRoot environment variable, if it is defined,
102 // and compute the number of characters required to store it in the
103 // envrionment block:
104 Character const system_root_name[] = { 'S', 'y', 's', 't', 'e', 'm', 'R', 'o', 'o', 't', '\0' };
105
106 __crt_unique_heap_ptr<Character> system_root_value;
107 if (_ERRCHECK_EINVAL(traits::tdupenv_s_crt(system_root_value.get_address_of(), nullptr, system_root_name)) != 0)
108 return errno;
109
110 size_t const system_root_value_count = system_root_value
111 ? traits::tcslen(system_root_value.get()) + 1
112 : 0;
113
114 size_t const system_root_count = _countof(system_root_name) + system_root_value_count;
115
116 // Compute the number of characters required to hold the environment
117 // strings provided by the user:
118 size_t const envp_count = [&]
119 {
120 size_t n = 2; // Account for double null terminator
121 for (auto it = envp; *it != nullptr; n += traits::tcslen(*it++) + 1) { }
122 return n;
123 }();
124
125 // Get the current environment from the OS so that we can get the current
126 // directory strings (those starting with '=') and append them to the user-
127 // provided environment.
128 __crt_unique_heap_ptr<Character> const os_environment(traits::get_environment_from_os());
129 if (!os_environment)
130 return EINVAL;
131
132 // Find the first shell environment variable:
133 Character* const first_cwd = [&]
134 {
135 Character* it = os_environment.get();
136 while (*it != '=')
137 it += traits::tcslen(it) + 1;
138 return it;
139 }();
140
141 // Find the end of the shell environment variables (assume they are contiguous):
142 Character* const last_cwd = [&]
143 {
144 Character* it = first_cwd;
145 while (it[0] == '=' && it[1] != '\0' && it[2] == ':' && it[3] == '=')
146 it += 4 + traits::tcslen(it + 4) + 1;
147 return it;
148 }();
149
150 size_t const cwd_count = last_cwd - first_cwd;
151
152
153 // Check to see if the SystemRoot is already defined in the environment:
154 bool const system_root_defined_in_environment = [&]
155 {
156 for (auto it = envp; *it != nullptr; ++it)
157 {
158 if (traits::tcsnicmp(*it, system_root_name, traits::tcslen(system_root_name)) == 0)
159 return true;
160 }
161
162 return false;
163 }();
164
165 // Allocate storage for the new environment:
166 size_t const environment_block_count = system_root_defined_in_environment
167 ? envp_count + cwd_count
168 : envp_count + cwd_count + system_root_count;
169
170 __crt_unique_heap_ptr<Character> environment_block(_calloc_crt_t(Character, environment_block_count));
171 if (!environment_block)
172 {
174 return errno = ENOMEM;
175 }
176
177 // Build the environment block by concatenating the environment strings with
178 // null characters between them, and with a double null terminator.
179 Character* result_it = environment_block.get();
180 size_t remaining_characters = environment_block_count;
181
182 // Copy the cwd strings into the new environment:
183 if (cwd_count != 0)
184 {
185 memcpy(result_it, first_cwd, cwd_count * sizeof(Character));
186 result_it += cwd_count;
187 remaining_characters -= cwd_count;
188 }
189
190 // Copy the environment strings from envp into the new environment:
191 for (auto it = envp; *it != nullptr; ++it)
192 {
193 _ERRCHECK(traits::tcscpy_s(result_it, remaining_characters, *it));
194
195 size_t const count_copied = traits::tcslen(*it) + 1;
196 result_it += count_copied;
197 remaining_characters -= count_copied;
198 }
199
200 // Copy the SystemRoot into the new environment:
201 if (!system_root_defined_in_environment)
202 {
203 static Character const equal_sign[] = { '=', '\0' };
204
205 _ERRCHECK(traits::tcscpy_s(result_it, system_root_count, system_root_name));
206 _ERRCHECK(traits::tcscat_s(result_it, system_root_count, equal_sign));
207 if (system_root_value)
208 {
209 _ERRCHECK(traits::tcscat_s(result_it, system_root_count, system_root_value.get()));
210 }
211 result_it += system_root_count;
212 }
213
214 // Null-terminate the environment block and return it. If the environment
215 // block is empty, it requires two null terminators:
216 if (result_it == environment_block.get())
217 *result_it++ = '\0';
218
219 *result_it = '\0';
220
221 *environment_block_result = environment_block.detach();
222 return 0;
223}
#define EINVAL
Definition: acclib.h:90
#define _ERRCHECK_EINVAL(e)
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define _countof(array)
Definition: sndvol32.h:70

Referenced by common_pack_argv_and_envp().

◆ throw()

Definition at line 293 of file cenvarg.cpp.

294{
295 Character** argv = caller_array;
296 size_t argv_count = caller_array_count;
297
298 __crt_unique_heap_ptr<Character*> local_array;
299
300 size_t i = 0;
301 Character* next_argument = const_cast<Character*>(first_argument);
302 for (;;)
303 {
304 if (i >= argv_count)
305 {
306 _VALIDATE_RETURN_NOEXC(SIZE_MAX / 2 > argv_count, ENOMEM, nullptr);
307
308 // If we have run out of room in the caller-provided array, allocate
309 // an array on the heap and copy the contents of the caller-provided
310 // array:
311 if (argv == caller_array)
312 {
313 local_array = _calloc_crt_t(Character*, argv_count * 2);
314 _VALIDATE_RETURN_NOEXC(local_array.get() != nullptr, ENOMEM, nullptr);
315
316 _ERRCHECK(memcpy_s(local_array.get(), argv_count * 2, caller_array, caller_array_count));
317
318 argv = local_array.get();
319 }
320 // Otherwise, we have run out of room in a dynamically allocated
321 // array. We need to reallocate:
322 else
323 {
324 __crt_unique_heap_ptr<Character*> new_array(_recalloc_crt_t(Character*, local_array.get(), argv_count * 2));
325 _VALIDATE_RETURN_NOEXC(new_array.get() != nullptr, ENOMEM, nullptr);
326
327 local_array.detach();
328 local_array.attach(new_array.detach());
329
330 argv = local_array.get();
331 }
332
333 argv_count *= 2;
334 }
335
336 argv[i++] = next_argument;
337 if (!next_argument)
338 break;
339
340#pragma warning(suppress:__WARNING_INCORRECT_ANNOTATION) // 26007 Possibly incorrect single element annotation on arglist
341 next_argument = va_arg(*arglist, Character*);
342 }
343
344 // At this point, we have succeeded; either local_array is null, or argv is
345 // local_array. In either case, we detach so that we can transfer ownership
346 // to the caller:
347 local_array.detach();
348 return argv;
349}
#define va_arg(ap, T)
Definition: acmsvcex.h:89
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define _VALIDATE_RETURN_NOEXC(expr, errorcode, retexpr)
#define SIZE_MAX
Definition: compat.h:66
int CDECL memcpy_s(void *dest, size_t numberOfElements, const void *src, size_t count)
Definition: heap.c:800

Variable Documentation

◆ first_argument