I need to rebuild a DLL that was last built years ago. I the have original C source code, but not the Visual Studio project or solution. I would like to try to rebuild it, using the same Visual Studio version that was used originally. I can tell that this is a plain old Windows DLL, not .NET. I also know that the source code is in C. Is there anything else I can tell about the original build environment and tools by examining the DLL binary?
Sure, this is totally possible. The key is that all PE-format images (the Windows format for executable binaries, including DLLs and EXEs) have headers that contain attributes and other information about the binary itself. Microsoft's toolchain always sets fields in that header that indicate the version of the tools used to build it. So you can just dump that header and examine those fields to find out what you want to know.
While there are third-party applications that can extract and pretty-print this information for you, the easiest way to get at it if you have any version of Visual Studio or the Windows SDK installed is dumpbin. Open a Visual Studio Command Prompt, type
dumpbin /headers <path to your DLL>, and press Enter. You'll get a big list of header data; don't let it intimidate you, you're only interested in a couple of fields.
Scroll up to the top. For a DLL, you'll see that the file type is a DLL (obviously). The first property in the "FILE HEADER VALUES" section is also sometimes interesting: it tells you whether the DLL is for a 32-bit or 64-bit machine. Then look under the next section, "OPTIONAL LINKER VALUES", for the "linker version" field. This, as I mentioned, is filled in by all Microsoft linkers with the version of the linker used to create the binary. The format is major.minor, so 14.00 is Visual Studio 2015, 10.00 is Visual Studio 2010, etc. There's a table of these version numbers on Wikipedia (the column you want is labeled "Version Number" here, since you want the version of the linker, not the version of the compiler, cl.exe). Other potentially interesting fields here are the "operating system version" and/or "subsystem version"—these will tell you which version of Windows that the binary was built to target. For example, 10.00 means Windows 10, 5.01 means Windows XP, and so on. Again, see Wikipedia for a table of Windows version numbers.
Another relevant piece of information might be which version of the C runtime library (CRT) that your binary links (assuming that it does, in fact, link to the CRT). You can determine this using dumpbin as well, but this time looking at the imports. (Or you can use something like Process Explorer to get a pretty-printed listing.) Run
dumpbin /imports <path to your DLL>, and then scroll through the list looking for something that begins with "MSVCR". The rest of the name indicates the version number. MSVCR80 means VC++ 8, or VS 2005. MSVCR90 means VC 9, or VS 2008. MSVCR100 means VC 10, or VS 2010. And so on.
All of this works even if symbols have been stripped from the binary.