Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333//// getenv.cpp//// Copyright (c) Microsoft Corporation. All rights reserved.//// Defines the getenv family of functions, which search the environment for a// variable and return its value.//#include <corecrt_internal_traits.h>#include <stdlib.h>#include <string.h>
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+//// getenv() and _wgetenv()////-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+// These functions search the environment for a variable with the given name.// If such a variable is found, a pointer to its value is returned. Otherwise,// nullptr is returned. Note that if the environment is access and manipulated// from multiple threads, this function cannot be safely used: the returned// pointer may not be valid when the function returns.template <typename Character>static Character* __cdecl common_getenv_nolock(Character const* const name) throw(){ typedef __crt_char_traits<Character> traits; Character** const environment = traits::get_or_create_environment_nolock(); if (environment == nullptr || name == nullptr) return nullptr;
size_t const name_length = traits::tcslen(name);
for (Character** current = environment; *current; ++current) { if (traits::tcslen(*current) <= name_length) continue;
if (*(*current + name_length) != '=') continue;
if (traits::tcsnicoll(*current, name, name_length) != 0) continue;
// Internal consistency check: The environment string should never use // a bigger buffer than _MAX_ENV. See also the SetEnvironmentVariable // SDK function. _ASSERTE(traits::tcsnlen(*current + name_length + 1, _MAX_ENV) < _MAX_ENV);
return *current + name_length + 1; }
return nullptr;}
template <typename Character>static Character* __cdecl common_getenv(Character const* const name) throw(){ typedef __crt_char_traits<Character> traits;
_VALIDATE_RETURN(name != nullptr, EINVAL, nullptr); _VALIDATE_RETURN(traits::tcsnlen(name, _MAX_ENV) < _MAX_ENV, EINVAL, nullptr);
Character* result = 0;
__acrt_lock(__acrt_environment_lock); __try { result = common_getenv_nolock(name); } __finally { __acrt_unlock(__acrt_environment_lock); } __endtry return result;}
extern "C" char* __cdecl getenv(char const* const name){ return common_getenv(name);}
extern "C" wchar_t* __cdecl _wgetenv(wchar_t const* const name){ return common_getenv(name);}
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+//// getenv_s() and _wgetenv_s()////-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+// These functions search the environment for a variable with the given name.// If such a variable is found, its value is copied into the provided buffer.// The number of characters in the value (including the null terminator) is// stored in '*required_count'. Returns 0 on success; returns ERANGE if the// provided buffer is too small; otherwise returns an error code on failure.template <typename Character>_Success_(return == 0)static errno_t __cdecl common_getenv_s_nolock( size_t* const required_count, _Out_writes_z_(buffer_count) Character* const buffer, size_t const buffer_count, Character const* const name ) throw(){ typedef __crt_char_traits<Character> traits;
_VALIDATE_RETURN_ERRCODE(required_count != nullptr, EINVAL); *required_count = 0;
_VALIDATE_RETURN_ERRCODE( (buffer != nullptr && buffer_count > 0) || (buffer == nullptr && buffer_count == 0), EINVAL);
if (buffer) buffer[0] = '\0';
Character const* const value = common_getenv_nolock(name); if (!value) return 0;
*required_count = traits::tcslen(value) + 1; if (buffer_count == 0) return 0;
// The buffer is too small; we return an error code and the caller can have // the opportunity to try again with a larger buffer: if (*required_count > buffer_count) return ERANGE;
_ERRCHECK(traits::tcscpy_s(buffer, buffer_count, value)); return 0;}
template <typename Character>_Success_(return == 0)static errno_t __cdecl common_getenv_s( size_t* const required_count, _Out_writes_z_(buffer_count) Character* const buffer, size_t const buffer_count, Character const* const name ) throw(){ errno_t status = 0;
__acrt_lock(__acrt_environment_lock); __try { status = common_getenv_s_nolock(required_count, buffer, buffer_count, name); } __finally { __acrt_unlock(__acrt_environment_lock); } __endtry return status;}
extern "C" errno_t __cdecl getenv_s( size_t* const required_count, char* const buffer, size_t const buffer_count, char const* const name ){ return common_getenv_s(required_count, buffer, buffer_count, name);}
extern "C" errno_t __cdecl _wgetenv_s( size_t* const required_count, wchar_t* const buffer, size_t const buffer_count, wchar_t const* const name ){ return common_getenv_s(required_count, buffer, buffer_count, name);}
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+//// _dupenv_s() and _wdupenv_s()////-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+// These functions search the environment for a variable with the given name.// If a variable is found, a buffer is allocated using the public malloc to hold// the value of the variable. The value is copied into the buffer and the buffer// is returned to the caller via 'buffer_pointer' and 'buffer_count'. The caller// is responsible for freeing the buffer.//// Returns zero on success; returns an error code on failure. Note that if a// variable with the specified name is not found, that is still considered a// success; in this case, the 'value' is an empty string ('*buffer_count' will// be zero and '*buffer_pointer' will be nullptr).template <typename Character>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 ) throw(){ // These are referenced only in the Debug CRT build UNREFERENCED_PARAMETER(block_use); UNREFERENCED_PARAMETER(file_name); UNREFERENCED_PARAMETER(line_number);
typedef __crt_char_traits<Character> traits;
_VALIDATE_RETURN_ERRCODE(buffer_pointer != nullptr, EINVAL); *buffer_pointer = nullptr;
if (buffer_count != nullptr) *buffer_count = 0;
_VALIDATE_RETURN_ERRCODE(name != nullptr, EINVAL);
Character const* const value = common_getenv_nolock(name); if (value == nullptr) return 0;
size_t const value_count = traits::tcslen(value) + 1;
*buffer_pointer = static_cast<Character*>(_calloc_dbg( value_count, sizeof(Character), block_use, file_name, line_number)); _VALIDATE_RETURN_ERRCODE_NOEXC(*buffer_pointer != nullptr, ENOMEM);
_ERRCHECK(traits::tcscpy_s(*buffer_pointer, value_count, value)); if (buffer_count != nullptr) *buffer_count = value_count;
return 0;}
template <typename Character>_Success_(return != 0)static errno_t __cdecl common_dupenv_s( _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 ) throw(){ errno_t status = 0;
__acrt_lock(__acrt_environment_lock); __try { status = common_dupenv_s_nolock( buffer_pointer, buffer_count, name, block_use, file_name, line_number); } __finally { __acrt_unlock(__acrt_environment_lock); } __endtry return status;}
extern "C" errno_t __cdecl _dupenv_s( char** const buffer_pointer, size_t* const buffer_count, char const* const name ){ return common_dupenv_s(buffer_pointer, buffer_count, name, _NORMAL_BLOCK, nullptr, 0);}
extern "C" errno_t __cdecl _wdupenv_s( wchar_t** const buffer_pointer, size_t* const buffer_count, wchar_t const* const name ){ return common_dupenv_s(buffer_pointer, buffer_count, name, _NORMAL_BLOCK, nullptr, 0);}
#ifdef _DEBUG
#undef _dupenv_s_dbg#undef _wdupenv_s_dbg
extern "C" errno_t __cdecl _dupenv_s_dbg( char** const buffer_pointer, size_t* const buffer_count, char const* const name, int const block_use, char const* const file_name, int const line_number ){ return common_dupenv_s(buffer_pointer, buffer_count, name, block_use, file_name, line_number);}
extern "C" errno_t __cdecl _wdupenv_s_dbg( wchar_t** const buffer_pointer, size_t* const buffer_count, wchar_t const* const name, int const block_use, char const* const file_name, int const line_number ){ return common_dupenv_s(buffer_pointer, buffer_count, name, block_use, file_name, line_number);}
#endif // _DEBUG