We were calling duplicate_environment() to copy the service's initial
environment prior to restarting it. However the duplicate_environment()
function modified its input by replacing = characters with NULLs. That
is not allowed; the memory returned by GetEnvironmentStrings() must be
treated as readonly.
After two restarts the application would run with a null environment and
probably crash.
We now copy the initial environment on to the heap and operate on the
copy, ensuring that the corruption does not occur.
Thanks Alessandro Gherardi.
The format_environment() and unformat_environment() functions could be
used to format any double null-terminated string list, and are not
specificially tied to formatting environment blocks.
useful_environment() skips the uninteresting variables at the start of
an environment block, returning a pointer to the first useful variable.
expand_environment_string() expands a string with
ExpandEnvironmentStrings() and returns a pointer to the expanded string,
which must be freed after use.
set_environment_block() iterates through all the variables in an
environment block, expands each one with expand_environment_string() and
calls SetEnvironmentVariable() with the expanded value.
clear_environment() removes all variables from the current environment.
duplicate_environment() duplicates an environment block by first calling
clear_environment() then set_environment_block() with the source block.
Thus it ensures that the variables in the block - and only those - are
set in the current environment.