Old DLLs on Modern Windows

Introduction

You may have run into a game from Windows 9x (usually 95) that either crashes or throws errors with either no indication, or mentions of broken or missing DLL files. This can be frustrating and hard to troubleshoot unless you know what to look for, and that's what this page will go over.

First off, look up the game in question and check out the version of DirectX it required when it came out. If it's below 7, it may (or may not) have compatibility issues - you'll most often see this with DX3 games in my experience.

If you're lucky, the program in question is throwing an error in a dialog box. It will be one of two types, in that case:

  • Missing DLL
  • Ordinal or Function not found in DLL

If you've got the former, then look at the missing DLL name. If it's something like a runtime (vbrun600.dll, ddraw.dll, msvcr70.dll, and infintely more) - you can check by searching for the DLL name and being observant of the context you find it in - then you simply need to provide it. You can either download the runtime installer, or install the file(s) manually. If you find msvcr70.dll is missing, for example, you need the Microsoft Visual C++ Runtime 7.0. With particularly old runtimes, the installer may not run, may refuse to run on your OS, or may do bad things if you do manage to install it. For this reason, unless it's a more recent runtime designed for 2k/XP+ (unlikely in these cases), I opt to install the files manually.

Note that when you are troubleshooting an x86 program, you want x86 versions of a runtime even when x64 is available - the x86 program will not use x64 DLLs, nor will it see them (Windows shows an x86 program SysWOW64 as System32 on an x64 version).

I've mirrored the version from the time of this writing (August 2012) in case it becomes unavailable in the future:

Dependency Walker 2.2 x86
Dependency Walker 2.2 x64


DLL Search Order

Let's stop for a moment to go over how Windows finds DLL files that an application requests, in what order:

  • (Your Exe Name).exe.config folder in the directory with the EXE
    • This is a feature added (I believe) with XP. The folder will not exist by default in most cases, and this method can be somewhat finnicky. In some cases, though, when the program bypasses other methods, this can work.
  • DLL files in the directory with the EXE
    • Any files found in the folder that the EXE resides in will take precedence over those on the path (explained next), so they can be used to override other versions of the same file without messing up the system's compatibility with newer programs. This is the most reliable method.
  • The PATH
    • PATH is an environment variable dating back to MS-DOS. It is a semicolon-delimited list of folder paths to check for files in, and it is checked in the order listed. If a file is not found in the .config folder or in the folder with the EXE, it will begin checking entries in the path one by one. By default the path includes places like c:\windows, and c:\windows\system32, etc.. You can add your own, however, if you find it necessary or desirable.

      You can do so in two ways:

      • With the PATH or SET command in a command prompt
        • PATH (New Path Here) - this overrides the existing path with the path you are entering
        • PATH %PATH%;(New Path Here) - this appends your new path parts to the end
        • PATH (New Path Here);%PATH - this does the opposite, prepending your path to the existing path
        • SET PATH=(New Path Here) - this works the same way as the PATH command, you can use %PATH%, etc.)
      • By using a GUI by going into System Properties
        • Right click "My Computer"
        • Hit Properties
        • If using Vista or higher, hit "Advanced Settings"
        • "Advanced" tab
        • "Environment Variables" button

It is worth noting here that there is a system called "Side-By-Side", AKA "WinSXS". There is a folder for this in c:\windows\winsxs, and it contains a confusing labrynth of files and folders. Windows automatically stores various versions of DLL files here, and keeps track of what programs use what for you. This eliminates a lot of problems you'd see in 9x where one program installs a DLL file over a newer/different one, breaking the first program, etc. - but it isn't foolproof. WinSXS is too complex to manually modify, so just be aware that if you can't find where a DLL file is coming from, it may be in there.

Armed with that knowledge, you can both locate a DLL file that is in use, and figure out where to place an overriding or missing one. I recommend placing DLLs for a program in the folder with the EXE (or if necessary the .config folder) for maximum safety, as the other methods are overkill in most cases, and this isolates your changes to the program in question.


Digging Deeper

Now, your program may have just not opened, have flashed up and then disappeared, or crashed with an irrelevant error, etc.. In this case you can't be sure that it's a DLL dependency error, but there is a good chance. First try installing any runtimes (manually or automatically) that the program shipped with, or was marked as requiring (such as DirectX levels). If that does not work, or does not resolve the problem entirely, we need to figure out what's wrong ourselves.

There's an excellent tool called "Dependency Walker" - this tool allows you to "ask" the EXE what it needs in order to run. For our purposes we want the x86 version - the x64 version is intended for x64 apps, and while it may work fine with most apps we are testing (I don't recall if it opens x86 or not..), just stick with the x86 one unless troubleshooting an x64 app.

Open the EXE in Dependency Walker and you will be greeted by a tree view of DLL files in the upper left box. The first level of DLLs are the ones that the program calls, while the ones below those are the DLLs that that DLL file calls, so on and so forth. Dependency Walker highlights DLL files yellow if they are missing something, and highlights them red if they are not present. In some cases it is fine if a DLL file is missing or not correct for this program, but you wouldn't be troubleshooting it if it was OK.

Look for any missing DLL files, and DLL files that appear to be a very wrong version, missing ordinals/functions/etc. that are being called, and note them.

Now it is time to learn to obtain the correct DLLs in a situation where they are missing and cannot be found in a runtime. You should not just download any version of the DLL that you find - this will lead to more broken calls, etc.. Look at what OS the program was designed to run on, what year it came out, etc., and attempt to determine what version of the DLL it expects. Ex. if it calls ddraw.dll, and came out in 1996 for Windows 95, it probably isn't asking for a ddraw.dll from DirectX 8.1. In this case, you'd look for a version from that era, probably by locating a DirectX 6 installer and extracting it. This process can include files that shipped with older versions of Windows, sometimes ones that are still in use as newer versions. This is why it is important to try to override the file just for the program itself, and not for the system - breaking things is not our goal.

Hopefully now your program is running - if not, there are other things to look at.