Thursday, July 12, 2007

Delay Load DLL and __HrLoadAllImportsForDll

Here are a few tips for delay loaded DLLs based on my experience with Visual Studio 2003 (Visual C++ 7.1)

  1. Delay load can be easily setup using the Visual Studio IDE by the following steps:
    • Open project property page: Linker > Input
    • In Additional Dependencies, add library: delayimp.lib;
    • In Delay Loaded DLLs, add all the DLLs you want to delay load.
      TIP #1: if you have more than one DLLs, the file names must be separated by ";", e.g.: rapi.dll;ceutil.dll. If you forget this, and try something like: rapi.dll ceutil.dll, then the linker will treat the whole string as the file name of a single file and fail to find a file with that name. There will be a subtle warning during build: LINK : warning LNK4199: /DELAYLOAD:rapi.dll ceutil.dll ignored; no imports found from rapi.dll ceutil.dll, which most likely will be ignored.
  2. Detect if the delay loaded DLLs exists on the host computer:
    The whole purpose of delay loaded DLLs is to allow our program to be more flexible. It can be loaded on computers that do not have certain DLLs, and it can choose to use those DLLs when they are present. So, there is always a need to know if we can load the delay loaded DLLs on the host computer. __HrLoadAllImportsForDll is the recommended function by MSDN documentation to do the job.
    TIP #2:Do not use __HrLoadAllImportsForDll because it use memcmp to compare DLL file names byte by byte which is too strict. File names in Windows system is not case sensitive, so the file names can be the same even if memcmp fails. This function will return module not found error code even when the DLL files are installed on host computer. I end up lift the implementation from delayhlp.cpp, and replace memcmp with _tcsicoll which is case insensitive.

No comments: