15#pragma warning(disable:__WARNING_POSTCONDITION_NULLTERMINATION_VIOLATION)
16#pragma warning(disable:__WARNING_MISSING_ZERO_TERMINATION2)
26template <
typename Character>
29 _In_z_ Character
const*
const environment_variable,
31 _In_ size_t const result_count
53 int const access_result = traits::taccess_s(
file_name, 0);
57 if (access_result == 0)
68 Character* path_string =
nullptr;
69 if (
_ERRCHECK_EINVAL(traits::tdupenv_s_crt(&path_string,
nullptr, environment_variable)) != 0 || path_string ==
nullptr)
75 __crt_unique_heap_ptr<Character>
const path_string_cleanup(path_string);
77 size_t const file_name_length = traits::tcslen(
file_name);
79 size_t const local_path_count =
_MAX_PATH + 4;
80 Character local_path_buffer[local_path_count];
82 size_t path_count = local_path_count;
83 Character* path_buffer = local_path_buffer;
84 if (file_name_length >= result_count)
89 path_count = traits::tcslen(path_string) + file_name_length + 2;
90 path_buffer = _calloc_crt_t(Character, path_count).detach();
98 __crt_unique_heap_ptr<Character> path_buffer_cleanup(path_buffer == local_path_buffer
105 Character*
const previous_path_string = path_string;
106 path_string = traits::tgetpath(path_string, path_buffer, path_count - file_name_length - 1);
107 if (!path_string && path_buffer == local_path_buffer &&
errno ==
ERANGE)
111 size_t const required_count = traits::tcslen(previous_path_string) + file_name_length + 2;
113 path_buffer_cleanup = _calloc_crt_t(Character, required_count);
114 if (!path_buffer_cleanup)
120 path_count = required_count;
121 path_buffer = path_buffer_cleanup.get();
123 path_string = traits::tgetpath(previous_path_string, path_buffer, path_count - file_name_length);
126 if (!path_string || path_buffer[0] ==
'\0')
140 Character
const last_character = *(path_it - 1);
141 if (last_character !=
'/' && last_character !=
'\\' && last_character !=
':')
152 if (traits::taccess_s(path_buffer, 0) != 0)
157 if (
path_length + file_name_length + 1 > result_count)
179 char const*
const environment_variable,
181 size_t const result_count
189 wchar_t const*
const environment_variable,
191 size_t const result_count
201 char const*
const environment_variable,
210 wchar_t const*
const environment_variable,
#define _ERRCHECK_EINVAL(e)
result_buffer_count char *const result_buffer
#define _VALIDATE_RETURN_ERRCODE(expr, errorcode)
#define _Out_writes_z_(s)
errno_t __cdecl _searchenv_s(char const *const file_name, char const *const environment_variable, char *const result_buffer, size_t const result_count)
void __cdecl _wsearchenv(wchar_t const *const file_name, wchar_t const *const environment_variable, wchar_t *const result_buffer)
static errno_t __cdecl common_searchenv_s(_In_z_ Character const *const file_name, _In_z_ Character const *const environment_variable, _Out_writes_z_(result_count) Character *const result_buffer, _In_ size_t const result_count)
errno_t __cdecl _wsearchenv_s(wchar_t const *const file_name, wchar_t const *const environment_variable, wchar_t *const result_buffer, size_t const result_count)
void __cdecl _searchenv(char const *const file_name, char const *const environment_variable, char *const result_buffer)