Я сейчас пишу свою собственную версию загрузчика Windows (хотя и очень простую), и пока все идет неплохо. Однако я столкнулся с небольшой загвоздкой, когда дело доходит до рекурсивного обхода таблицы импорта для загруженного модуля.
Для большинства зависимостей все работает хорошо, и я могу просто рекурсивно загрузить модуль. Однако для некоторых зависимостей это просто нарушает целевой процесс. После дальнейшего расследования я понял, что это из-за параллельных сборок Windows. По сути, зависимость в загруженном PE была другой версией SxS модуля, используемого в целевом процессе.
В одном случае загружаемая мной библиотека DLL ссылалась на msvcr90.dll, но целевой процесс использовал более раннюю версию среды выполнения: msvcr71.dll.
Теперь загрузчик Windows может справиться с этим нормально, так что, очевидно, есть правильный способ сделать это. Я немного читал о контекстах активации, но они не помогли мне разобраться в проблеме.
Вызов LoadLibrary сам по себе не переводит dll в правильную версию.
LoadLibraryW(L"msvcr90.dll");
Просто возвращает 0. Кто-нибудь знает
а) Как определить, является ли импорт сборкой SxS
б) Как разрешить импорт в правильную версию SxS для процесса.
Я действительно не понимаю, как это сделать. Я знаю большую часть формата файлов PE из исследований, но я почти уверен, что SxS выходит за рамки структуры PE.
Если вам нужна дополнительная информация, просто прокомментируйте. У исполняемого файла нет внешнего манифеста, а его встроенный манифест не указывает версию среды выполнения. Однако он содержит копию msvcr71.dll в своем рабочем каталоге, если это кому-то вообще поможет.
Ваше здоровье.
.dll
(RT_MANIFEST). Затем мне пришлось написать заглушку сборки, которая обрабатывала всеActivation Context
вещи. Конечно, я мог бы просто написать его на C ++ и обернуть в .dll со статической связью (то есть без SxS), а затем использовать его для загрузки всех следующих библиотек, но это казалось излишним, поэтому я сделал это в сборке. По сути, я скармливаю функции сборки строку с необходимыми зависимостями, разделенную нулем ... - person Jason Larke   schedule 20.07.2012CreateActCtx
нужен путь к манифесту). Затем он создает контекст активации, просматривает список модулей, разделенных нулями, и вызываетGetModuleHandle
для каждого из них. ЕслиGetModuleHandle
возвращает0
, он переходит к вызовуLoadLibrary
. Если по-прежнему 0, функция выходит из функции. Я знаю, что пропустил самую сложную часть, просто используяLoadLibrary
вActivation Context
, но я действительно хотел использовать свой собственный загрузчик только для основной dll, а не для ее зависимостей. - person Jason Larke   schedule 20.07.2012