LoadLibraryEx игнорирует параллельный манифест

Есть ли LoadLibraryEx функция использования параллельных манифестов? У меня есть bar.dll со встроенным манифестом SxS, и этот манифест описывает версию этого bar.dll, другой dll-файл foo.dll имеет манифест, который перечисляет bar.dll как зависимость с указанной версией. Но когда я пытаюсь загрузить bar.dll из foo.dll с LoadLibraryEx("bar.dll", NULL, 0) Я вижу (с включенным sls с gflags), что он игнорирует эти манифесты и загружает первую версию bar.dll, которую видит в searchpath, если я определяю ISOLATION_AWARE_ENABLED и использовать LoadLibrary он находит правильную версию, но это ISOLATION_AWARE_ENABLED не влияет на поведение LoadLibraryExМне нужно загрузить правильную версию с LoadLibraryEx так как LoadLibraryEx используется неявно для отложенной загрузки DLL. Является LoadLibraryEx должен работать так, или это какая-то проблема в конфигурации моего проекта?

фу длл

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="foo" version="0.1.2.3" type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity name="bar" version="0.1.2.3" type="win32" />
</dependentAssembly>
</dependency>
<file name="foo.dll">
</file>
</assembly>

bar.dll

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="bar" version="0.1.2.3" type="win32"/>
<file name="bar.dll">
</file>
</assembly>

3

Решение

LoadLibrary использовал активный контекст активации вызывающего потока. но что это за контекст? почему это должно быть от вашего foo.dll ? почему не из xyz.dll или из exe? действительно, наиболее активным контекстом активации времени был именно exe.

если у dll есть собственный манифест — система создает контекст активации для этой dll и сохраняет его (пока dll не будет выгружен), но не делает его активным. и это очевидно — у нас есть несколько dll в процессе, но активный контекст только один — из какой dll его выбрать? из exe. однако система активирует (делает ее активной) контекст активации dll перед вызовом точки входа. и деактивировать его после возврата к точке входа. но скажем внутри других функций dll — (кто это вызвал?) контекст уже не из вашей dll.

поэтому решение должно быть следующим:

определить 2 глобальные переменные в dll:

BOOL gActCtx;
HANDLE ghActCtx

на DLL_PROCESS_ATTACH сохранить текущий контекст активации (это из вашего dll-манифеста)

gActCtx = GetCurrentActCtx(&ghActCtx);

освободи его на DLL_PROCESS_DETACH

if (gActCtx) ReleaseActCtx(ghActCtx);

и когда вам нужно загрузить bar.dll делать дальше:

if (gActCtx)
{
ULONG_PTR Cookie;

if (ActivateActCtx(ghActCtx, &Cookie))
{
LoadLibraryExW(L"bar.dll", NULL, 0);

DeactivateActCtx(0, Cookie);
}
}
5

Другие решения

Других решений пока нет …