4

I'm currently programming a Python interface for a C++ project using Boost Python. The problem is that if a DLL is missing Python gives us a very unhelpful error message:

ImportError: DLL load failed: The specified module could not be found.

According to this site it isn't possible to display more information than this.

Now, the big issue. I cannot use dependency walker or dumpbin because we need to be able to programmatically determine which DLL is missing. The good news is that we are only required to check the first level of dependencies. So, if my.exe is dependent on a.dll, b.dll, and c.dll then that is the only set of DLLs we're interested in. If a, b, and c are all where they should be then my job is done.

I have already found this MSDN page on enumerating for a running process but have been unable to find out how to do so for a non-running .exe or unloaded .dll. The closest I've come is an MSDN article about the LoadLibraryEx function*. However, I cannot for the life of me figure out how to get the dependency table from the returned HMODULE.

So, the $64,000 question is: how do I get the .exe/.dll dependencies from the HMODULE? An even better question is: Is that where I get the dependencies? If not then where can I find it?

The optimal solution would be in C++ but we're more than happy to have a Python solution as well. Any help or suggestions would be appreciated. Thanks.

* I'd link the article but my rep isn't high enough to post two links in one question. :)

soulsabr
  • 895
  • 4
  • 16
  • The _Python_ you link against when you build your dll is the same as the one you run it with? Are there all the required dlls (e.g. the _Boost_ one) in the same folder as the exe (or available somewhere in _%PATH%_ ?) Also, be careful to 32/64 bits mismatches. – CristiFati Nov 23 '15 at 22:50
  • We've never had an issue with Boost or Python DLLs missing. The problem is that an incorporated library, for one reason or another, is not there. For example, we wrap library A using boost python and the DLL for library A isn't where it is supposed to be. We only get the above error instead of something along the lines of "Can't find a.dll". – soulsabr Nov 23 '15 at 23:39
  • What _Python_ are you using? Do you by any chance have [pywin32](https://sourceforge.net/projects/pywin32/) installed? So, you are trying to import a module (_.pyd_) written in _C_ that depends on a set of libs and one might not be there, but you want to programmatically determine which one. If that's the case, `HMODULE` can't be used since the very existence of the `HMODULE` object (different than `NULL`) implies that the dll has already been successfully loaded. – CristiFati Nov 23 '15 at 23:49
  • Yes, pywin32. OK, I did not know that I'd only get an HMODULE if all DLL dependencies are present. We all know how great the MSDN documentation is. That is good to know for the future. Thanks for the info. Hopefully Nick Cano's suggestions will do the trick for me. – soulsabr Nov 24 '15 at 14:42

1 Answers1

4

You need to read the Portable Executable Header (PE Header) of the module. This is a structure that describes the imports, exports, re-locations, sections, resources, code, static data, and everything else the binary relies on. While it can be parsed directly, the PE Header structure has a lot of quirks and nuances that aren't obvious. I'd recommend using a library, such as PeLib, to handle everything for you.

Samuel Liew
  • 76,741
  • 107
  • 159
  • 260
Nick Cano
  • 437
  • 2
  • 7
  • Downloaded PeLib. I'll let you know how it works out for me. If nothing else at least now I know about the PE Header. EDIT : I'm 4 rep away from being able to give you a +1. – soulsabr Nov 23 '15 at 23:45
  • No worries about the rep :) If you're having issues with PeLib (it's a bit of a messy template-heavy library, so it can be a bit frustrating), and you're still willing to use Python, you might try something like [this](https://github.com/trailofbits/pe-parse/tree/master/python) or [this](https://github.com/erocarrera/pefile). – Nick Cano Nov 23 '15 at 23:49
  • Hah, level up! +1 to ya. I got PeLib compiled. For some odd reason they redefined 'for' with a macro. VS2013 did not like that. Anyhow, thanks for the links. I'll give them all a good once over. Even if PeLib does the job the others could come in handy in the future. Thanks. – soulsabr Nov 24 '15 at 14:39
  • It works! Yup, PeLib is a mess. They redefine things to what appears to be the exact same value for no apparent reason. However, it works. It lists all of the DLL dependencies for me and isn't a huge pain to use once compiled. Thanks, this will save me a great deal of time. – soulsabr Nov 24 '15 at 15:20