History with the transfer of the environment variable. Different versions of msvcrt, UAC
A seemingly simple task arose - configuring a third-party library through an environment variable. In our process we do the following:
set some environment variable VAR = str
load library library
call the foo () function of this library
Everything works, but suddenly it turns out that the library stops working correctly on my home machine. Moreover, if you run as an administrator, it still works fine. Thoughts are very different, the library is complex and the mass of influencing factors. In the end, it turns out the following fact - getenv () does not work with the actual environment of the process, but with its copy inside the msvcrt library. Having learned it we remember that the third-party library uses msvcrt8, and we msvcrt10. We look in the debugger order of loading libraries and find out the difference. Without administrator rights (does not work):
our process implicitly loads msvcrt10
hook hooks the logitech library for the wireless keyboard (to intercept any key combinations, it is displayed in all processes)
logitech implicitly pulls msvcrt8 behind itself, initializes its copy of the environment
we change the environment msvcrt10.putenv (var = str)
load library.dll
msvcrt8 already in memory
call library.foo (), it calls msvcrt8.getenv (VAR), which returns an empty var, because msvcrt8 initialized before changing environment
Now with administrator rights (works correctly):
our process implicitly loads msvcrt10
hook logitech library does not load, for security reasons, this is how the system works.
we change the environment msvcrt10.putenv (var = str)
load library.dll
implicitly loaded msvcrt8, reads the current environment where the var is installed
call library.foo (), it calls msvcrt8.getenv (VAR), which returns var = str
Conclusion. You can not rely on the fact that setting the environment variable it will see a third-party library, because there is no guarantee that someone will not implicitly load another CRT. The correct way is to set up the environment and start the child process. That was done. The multiplicity of CRT libraries generates not only problems of memory management and CRT library objects, but also such wonderful phenomena.