2017-02-05 5 views
0

상황은 다음과 같습니다. 이러한 DLL은 프로세스에로드됩니다해결 방법 LoadLibraryEx (..., LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) 잘못된 DLL로드 버그

c:\abc\foo.dll 
c:\abc\bar.dll 
c:\zxc\foo.dll 

그리고 그 과정은 c:\abc\에 있습니다. 로드 중입니다. c:\zxc\bar.dll입니다. 암시 적으로 foo.dll에 연결됩니다. 그리고 같은 폴더에있는 c:\zxc\foo.dll에 링크해야합니다. 나는 다음 c:\zxc\foo.dll가 제대로로드되는 c:\abc\foo.dll이 과정에서로드되지

LoadLibraryExA("c:\\zxc\\bar.dll", NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR) 

경우에로드하고 그것에 c:\zxc\bar.dll 링크. 그러나 c:\abc\foo.dll이로드 된 경우 c:\\zxc\\bar.dllc:\zxc\foo.dll 대신 c:\abc\foo.dll (심지어 c:\zxc\foo.dll이 이미로드 된 경우에도 있음)으로 연결됩니다. 이것은 글로벌 플래그의 "Show loader snaps"체크 박스의 도움으로 확인되었습니다.

어떻게 해결할 수 있습니까?

bar.dll은 제 3 자이므로 DELAYLOAD를 구현할 수 없습니다.

그리고 c:\abc\foo.dll을로드하는 것을 막을 수 없습니다.

나는 ntdll!LdrpFindOrMapDll을 연결하려고 생각하고 있지만 신뢰할 수없는 것처럼 보입니다. 지원되는 모든 Windows 버전에서이를 철저히 테스트해야하므로 간단한 해결 방법을 먼저 찾습니다.

+2

여기에 버그가 없습니다. 라이브러리 함수는 의도 된대로 작동합니다. 모듈이 이름으로 만 암시 적으로 링크되고 해당 이름의 모듈이 이미 프로세스에로드 된 경우 해당 모듈이 링크 된 모듈입니다. 그것은 모두 설계 상입니다. –

+1

foo.dll의 이름을 변경할 수없는 이유가 있습니까? 이름을 변경하면 모든 문제가 해결 방법을 고민하지 않고 사라집니다. – theB

+0

이론적으로,'c : \ zxc \ bar.dll' *을로드하기 전에'c : \ abc \ foo.dll'을로드하면 제대로 작동합니다. 명시 적 경로를 통해 후자를로드하면 제공됩니다. (또는'bar.dll'의 두 복사본 모두 해당 foo.dll을 암시 적으로로드합니까?) –

답변

1

나는 foo.dll을 side-by-side 어셈블리로 만들고 DLL manifest에서 참조 할 수 있다고 생각한다. 이것은 예를 들어, 5 및 6 버전의 공용 컨트롤과 Visual Studio의 다른 C 런타임 버전이 동일한 프로세스에서 공존하는 방식입니다.

이 방법을 사용하면 foo.dll을 WinSxS 폴더에 설치할 필요가 없습니다. 개인 어셈블리로 할 수 있습니다.

side-by-side 어셈블리가 작동하지 않으면 연결 솔루션이 복잡하고 위험합니다. 생각해보십시오 : GetModuleHandleW (L "foo.dll")와 같은 호출 수가 각 컨텍스트에서 적절한 하나의 DLL 핸들을 반환해야합니다! (그리고 ISOLATION_AWARE_ENABLED가 정의 된 상태에서 bar.dll 코드가 컴파일 된 경우 side-by-side 어셈블리가이 트릭을 수행함)