views:

166

answers:

5

Our product includes several DLLs built from open source into files with default names as delivered by the open source developers. We're careful to install the files in our own directories and we carefully manage the search path (only for our processes) to keep the loader happy.

Another developer -- a towering intellect -- decided it would be easier to install their own build of some of the same open source into C:\WINDOWS under the same default DLL filenames. Consequently, when we launch a process which depends on these open source DLLs, the system searches C:\WINDOWS before our directories and finds the DLLs installed by the other developer. And they are, of course, incompatible.

Ideas which have occurred to me so far:

  • rename all our DLLs to avoid the default names, which would only make it less likely we would encounter collisions
  • load all our DLLs by full path so the loader captures their names into RAM and doesn't search anywhere else the next time they are requested

For various reasons, neither of these options is palatable at the moment.

What else can we do to defend ourselves against the towering intellects of the world?

+5  A: 

You've got only two options: deploy the DLL in the same directory as the EXE (that's where Windows looks first) or using manifests and deploy the DLL to the Windows side-by-side cache. I don't think the latter option is common in the Open Source world but it is the only real fix if you want to share DLLs between different apps.

Hans Passant
Yeah, the latest documentation (which by the way seems to be at http://msdn2.microsoft.com/en-us/library/ms972822.aspx) doesn't mention the EXE's directory, but I just did an experiment which I think establishes that.
Integer Poet
Better documentation here:http://msdn.microsoft.com/en-us/library/ms682586(VS.85).aspx
Integer Poet
A: 

strong name
link text

tsinik
A: 

Maybe just compile them to a static library?

Why not?

Also, the current directory, where the exe is activated from is searched before c:\windows.

shoosh
We have many, many EXEs. Compiling the DLLs statically into all of them would make them prohibitively large. As well, there are multiple teams involved which operate on cooperative schedules and the DLLs provide a way to manage deliverables.
Integer Poet
And, by the way, the current directory is NOT searched before system directories as of XP SP1 and Server 2003 UNLESS you do something with SetDllDirectory which is unclear from the available documentation. (If I were to take this approach, I would just pass the current directory to eliminate all doubt.) However, I think what you really meant is that the EXE's parent directory is searched first, and that is indeed true.
Integer Poet
Yes, that's what I was saying. why doesn't that solve your problem?
shoosh
The DLLs aren't located in the same directory as the EXEs.
Integer Poet
+1  A: 

The directory from which the application loaded is normally the first directory searched when you load a DLL. You can, however, use SetDllDirectory to get the "alternate search order". In this case, the directory you specify to SetDllDirectory gets searched first.

There is also a SafeDllSearchMode that affects this to a degree. Turning it on excludes the current directory from the search.

Jerry Coffin
The trouble with SetDllDirectory is that the value isn't inherited by child processes. We have many child and grandchild (and probably deeper) processes.SafeDllSearchMode does sound intriguing and I'm looking into it.
Integer Poet
`SafeDllSearchMode` does not remove the current directory from the search path. Rather, it moves the current directory toward the end of the places to look. That can help. If you're trying to load a system library or one installed with your executable, you're all set. But if you're doing a `LoadLibrary` to determine whether a DLL exists, then that still leaves you open to a preload attack.
Adrian McCarthy
+2  A: 

To add to the already excellent answers, you have a couple more choices:

The preferred solution(s) to this problem, supported since Windows XP, is to turn your dll's into a win32 assembly (They don't have to be .NET but the documentation on creating win32 assemblies with strong names is appallingly light so its easy to get confused and think this is a .NET only technology).

An assembly is noting more complicated than a folder (With the name of the assembly) containing the dlls and a .manifest (With the name of the assembly) that contains an assemblyIdentiy element, and a number of file nodes for each dll in the assembly.

Assembly based searching works even when dlls are statically linked!

  • The easiest option is to create unversioned assemblies and store them in the same folder as your .exe files (Assuming all your exe's are in a single folder).

If the exe's are in different folders, then there are two ways to access shared assemblies:

  • You can store your assemblies in a private alternate location if you expect your application to be used on Windows 7 and higher. Create a app.exe.config file for each of your exe's, and point a probing privatePath element to a common folder where you are storing the assemblies.

  • If you are ok with requiring administrative access to perform installs, (via MSI's) then you can deal with the appallingly bad documentation (well, absent documentation) that deals with giving your assemblies a strong name, and then store the assembly in WinSxS.

If you can't, or do not want to bundle your dlls as assemblies then this page covers dll search order

Using functions like SetDllDirectory are only going to help for dlls loaded dynamically at runtime (via LoadLibrary).

Dll search order used to be:

  1. Directory containing the process exe
  2. Current directory
  3. various windows folders
  4. PATH

Which you could have used to your advantage - launch each exe, setting the "current" directory to the folder containing the OSS dlls.

With the advent of SafeDllSearchMode the search order now is:

  1. Directory containing the process exe
  2. various windows folders
  3. Current directory
  4. PATH

Meaning theres now less control than ever :( - It goes even faster to the "untrusted" c:\windows & System32 folders.

Again, if the initial dll is being loaded via LoadLibrary, and its the dependent dll's that are the problem, LoadLibraryEx with the LOAD_WITH_ALTERED_SEARCH_PATH flag will cause the following search order (Assuming you pass a full path to LoadLibraryEx) :-

  1. Directory part of the Dll path passed to LoadLibraryEx
  2. various windows folders
  3. Current directory
  4. PATH
Chris Becke