Click here to Skip to main content
6,594,932 members and growing! (17,211 online)
Email Password   helpLost your password?
General Programming » DLLs & Assemblies » General     Intermediate

Dynamic DLL Loading

By Zoran M. Todorovic

How to dynamically load a DLL
VC6, Dev
Posted:29 Dec 1999
Views:204,988
Bookmarked:64 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
21 votes for this article.
Popularity: 5.65 Rating: 4.28 out of 5

1

2
1 vote, 14.3%
3
4 votes, 57.1%
4
2 votes, 28.6%
5
  • Download demo project - 11 Kb
  • Usually, programmers use static linking when using functions in a DLL. This is the most easiest way to use a DLL. However, if a DLL is missing, application cannot be started. This is not a big problem: missing DLL means that something is wrong with application installation and the application should not be started anyway.

    However, if an application is designed in such a way as to offer some optional features with the help of one or more DLLs, missing DLL should not prevent the application to run normally (but without optional features). In this case, DLL must be loaded dynamically. This article presents a base class which offers all the necessary functionality for dynamic DLL loading. It is limited to DLLs exporting plain functions (not C++ classes). This is not a big limitation since all platform DLLs are written in this way. DLLs which export C++ classes are almost always used with static linking.

    Complete functionality is implemented in a class TDllModule. This class is not intended to be used directly, instead programmers should derive application specific class and extend it in a way explained in the following example. Only 2 virtual functions are important in this class: Create() and Destroy(). Create() function returns TRUE if the DLL is loaded correctly and an instance handle obtained. Destroy() will unload the DLL from process memory.

    Let's assume that some application needs the services of Microsoft's PSAPI (Process Status API) DLL to enumerate all running processes and display process executable filename. PSAPI DLL may not be installed on the machine since it is not part of the operating system. So, we need to dynamically load it and check whether it is loaded before using it.

    Therefore, we create a class TProcessStatusModule derived from TDllModule. We also need to create typedefs for functions needed from the DLL (this is not necessary but will keep the code easier to read).

    // This prototypes are obtained (copy and paste) from the DLL include file
    
    
    typedef BOOL (WINAPI *TFEnumProcesses)(
    	DWORD * lpidProcess, DWORD cb, DWORD * cbNeeded
    );
    typedef BOOL (WINAPI *TFEnumProcessModules)(
    	HANDLE hProcess, HMODULE *lphModule, DWORD cb, LPDWORD lpcbNeeded
    );
    typedef DWORD (WINAPI *TFGetModuleBaseName)(
    	HANDLE hProcess, HMODULE hModule, LPSTR lpBaseName, DWORD nSize
    );
    typedef DWORD (WINAPI *TFGetModuleFileNameEx)(
    	HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize
    );
    typedef BOOL (WINAPI *TFGetModuleInformation)(
    	HANDLE hProcess, HMODULE hModule, LPMODULEINFO lpmodinfo, DWORD cb
    );
    
    class TProcessStatusModule : public TDllModule {
    private:
        TFEnumProcesses FEnumProcesses;
        TFEnumProcessModules FEnumProcessModules;
        TFGetModuleBaseName FGetModuleBaseName;
        TFGetModuleFileNameEx FGetModuleFileNameEx;
        TFGetModuleInformation FGetModuleInformation;
    
    public:
        TProcessStatusModule();
        virtual ~TProcessStatusModule();
    
        virtual BOOL Create(void);
        virtual void Destroy(void);
        
        BOOL EnumProcesses(DWORD * lpidProcess, DWORD cb, DWORD * cbNeeded);
        BOOL EnumProcessModules(HANDLE hProcess,HMODULE *lphModule,DWORD cb,
                                LPDWORD lpcbNeeded);
        DWORD GetModuleBaseName(HANDLE hProcess,HMODULE hModule,LPSTR lpBaseName,
                                DWORD nSize);
        DWORD GetModuleFileNameEx(HANDLE hProcess,HMODULE hModule,
                                  LPSTR lpFilename,DWORD nSize);
        BOOL GetModuleInformation(HANDLE hProcess,HMODULE hModule,
                                  LPMODULEINFO lpmodinfo,DWORD cb);
    };
    

    Most important function in the class example above is Create(). It needs first to call the base class that loads the DLL into the process memory and obtains a handle and second, to obtain pointers to functions in a DLL that are needed for the current application. If this function returns FALSE, then the DLL is not loaded correctly and cannot be used. Its implementation is the following:

    BOOL TProcessStatusModule::Create(void)
    {
      if (TDllModule::Create()) {
        // DLL handle is valid (DLL is loaded)
    
        FEnumProcesses = (TFEnumProcesses)::GetProcAddress(m_hHandle,
                                                           _T("EnumProcesses"));
        FEnumProcessModules = (TFEnumProcessModules)::GetProcAddress(m_hHandle,
                                                           _T("EnumProcessModules"));
        // Load all other needed functions
    
        ...
        // Can also check if all pointers to functions are different from NULL.
    
        return TRUE;
      }
      return FALSE;
    }
    

    All that is left to be done is the actual execution of functions in a DLL. All DLL functions needed in the application have a corresponding method in the class above (each method has exactly the same arguments as the actual DLL function, the return code is also the same). Example of one function is the following:

    BOOL TProcessStatusModule::EnumProcesses(DWORD *lpidProcess, DWORD cb, DWORD *cbNeeded)
    {
      ASSERT(FEnumProcesses != NULL);
      if (FEnumProcesses) 
          return FEnumProcesses(lpidProcess,cb,cbNeeded);
      return FALSE;
    }
    

    The only remaining issue is the error handling of the function(s) like the one above. Original DLL function returns BOOL as the function above. Even if the DLL is loaded correctly, we still do not know (if the return code of the function is FALSE) whether the function really returned FALSE or the function is not defined as exported from the DLL (this is valid for release version of the code since debug version will assert). There are 2 solutions for this problem:

    1. Check whether all needed DLL functions are exported from the DLL (in Create()) by comparing all obtained function pointers to NULL. If any one of them is NULL, unload the DLL and prevent application to use it.
    2. In the function above (and all other functions), use exception handling instead of a simple return code. If the function succeeds then it is guarantied that the return code comes from the DLL function.

    I have used this technique in many application for DLLs like Winsock2, TAPI, PDH (Performance Data Helper), PSAPI (Process Status API) and similar.

    Latest update of this article may be found here.

    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here

    About the Author

    Zoran M. Todorovic


    Member
    I am a cofounder of SCA Software, company that specializes in software for process control, visualization and communication. Programming for the last 10 years in C++, Delphi. Visual C++ for the last 6 years. Degree in Electronics Engineering and Telecommunications.
    Occupation: Web Developer
    Company: SCA d.o.o.
    Location: Serbia Serbia

    Other popular DLLs & Assemblies articles:

    Article Top
    You must Sign In to use this message board.
    FAQ FAQ 
     
    Noise Tolerance  Layout  Per page   
     Msgs 1 to 25 of 29 (Total in Forum: 29) (Refresh)FirstPrevNext
    General[Message Deleted] Pinmemberit.ragester6:38 28 Mar '09  
    GeneralHow to update dll file if the dll file has been used by some application? Pinmembercharcoalc17:36 28 Apr '05  
    GeneralRe: How to update dll file if the dll file has been used by some application? Pinmembersaporob13:02 12 Sep '05  
    Generalplugin Pinmemberdoctrane7:56 24 Sep '04  
    Generaldll??? Pinmemberdnqhung2:28 10 Jun '04  
    General"psapi.h" PinmemberNunix696:50 19 Mar '04  
    GeneralRe: "psapi.h" PinmemberDaaawq dwdapodw13:22 1 Oct '04  
    GeneralDynamic Loading of DLL Export Class possible?? Pinmemberrubel_dreams19:37 23 Jul '03  
    GeneralCreat dll with library using library of visibroker Pinmemberngtrungthanh22:31 29 Jun '03  
    GeneralEditbox control PinsussN.0:10 18 Jul '02  
    GeneralAbout .def file PinmemberVijay7819:17 19 Apr '01  
    GeneralRe: About .def file PinmemberJuha Silmujarvi0:37 12 Mar '03  
    GeneralATL Dll Pinmemberyamini18:15 8 Feb '01  
    GeneralATL Dll Pinmemberyamini18:15 8 Feb '01  
    GeneralRe: ATL Dll PinmemberAnonymous3:24 25 May '01  
    GeneralATL Dll Pinmemberyamini18:13 8 Feb '01  
    GeneralATL Dll Pinmemberyamini18:12 8 Feb '01  
    GeneralWhy can't i assign a CString varible of Dialog in DLL PinmemberHoang Huy22:16 26 Nov '00  
    GeneralRe: Why can't i assign a CString varible of Dialog in DLL PinmemberAlbert van Peppen1:46 23 Jul '01  
    GeneralRe: Why can't i assign a CString varible of Dialog in DLL PinmemberZoltan Gozerson6:53 27 Sep '07  
    GeneralDLL exporting C++ classes PinsussJörg1:51 2 Oct '00  
    GeneralRe: DLL exporting C++ classes PinsussPeterK11:35 10 Oct '00  
    GeneralRe: DLL exporting C++ classes Pinmembersobinov3:26 3 Jan '01  
    GeneralRe: DLL exporting C++ classes PinmemberSurprised13:27 3 Jan '01  
    GeneralRe: There has been an article submitted on this subject. PinsussPeterK11:40 10 Oct '00  

    General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    PermaLink | Privacy | Terms of Use
    Last Updated: 29 Dec 1999
    Editor: Chris Maunder
    Copyright 1999 by Zoran M. Todorovic
    Everything else Copyright © CodeProject, 1999-2009
    Web21 | Advertise on the Code Project