Возникла казалось бы простая задача – конфигурирование сторонней библиотеки через переменную окружения. В нашем процессе делаем следующее:
Мысли самые разные, библиотека сложная и масса влияющих факторов. В конце концов выясняется следующий факт – getenv() работает не с реальным окружением процесса, а с его копией внутри библиотеки msvcrt. Узнав это вспоминаем, что сторонняя библиотека использует msvcrt8, а мы msvcrt10. Смотрим в отладчике порядок загрузки библиотек и выясняем разницу. Без прав администратора (не работает):
- установить некую переменную окружения VAR=str
- подгрузить библиотеку library.dll
- вызвать функцию foo() этой библиотеки
Мысли самые разные, библиотека сложная и масса влияющих факторов. В конце концов выясняется следующий факт – getenv() работает не с реальным окружением процесса, а с его копией внутри библиотеки msvcrt. Узнав это вспоминаем, что сторонняя библиотека использует msvcrt8, а мы msvcrt10. Смотрим в отладчике порядок загрузки библиотек и выясняем разницу. Без прав администратора (не работает):
- наш процесс неявно грузит msvcrt10
- загружается hook библиотека logitech для беспроводной клавиатуры (для перехвата каких-то комбинаций кнопок, отображается во все процессы)
- logitech неявно за собой тянет msvcrt8, инициализирует свою копию окружения
- мы меняем окружение msvcrt10.putenv(VAR=str)
- грузим library.dll
- msvcrt8 уже в памяти
- вызов library.foo(), она обращается к msvcrt8.getenv(VAR), который возвращает пустой VAR, т.к. msvcrt8 инициализировалась до изменения окружения
- наш процесс неявно грузит msvcrt10
- hook библиотека logitech не загружается, по соображениям безопасности, так работает система
- мы меняем окружение msvcrt10.putenv(VAR=str)
- грузим library.dll
- неявно грузится msvcrt8, считывает текущее окружение, где VAR установлен
- вызов library.foo(), она обращается msvcrt8.getenv(VAR), который возвращает VAR=str