Search code examples
c++dllmfcdialogafx

MFC extension dll resources loading problems


I have built the folowing configuration:

  • A) MFC Extension DLL having 2 MFC dialogs.
  • B) MFC regular dll that uses DLL A functions.
  • C) win32 application (NON MFC) calling for function from DLL B

When calling functions from DLL B that inside call functions from DLL A to display a dialog an error occurs due to the fact that resource can not be found.

I have digged to find the exact root cause and themain reson seems to be the fact that the module context is set to the calling dll B rather than to the DLL A, which contains the dialog resource.

Inside DllMain the initialization is done as described in the MSDN:

static AFX_EXTENSION_MODULE NEAR extensionDLL = { NULL, NULL };

extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{   
   if (dwReason == DLL_PROCESS_ATTACH)
   {      
       Hinstance = hInstance;  //save instance for later reuse
      // Extension DLL one-time initialization
      if (AfxInitExtensionModule(extensionDLL,hInstance) == 0)
      {
          AfxMessageBox("Error on init AfxInitExtensionModule!");
          return 0;
      }
      // Insert this DLL into the resource chain
      new CDynLinkLibrary(extensionDLL);
   }
   else if (dwReason == DLL_PROCESS_DETACH)
   {
       Release();
   }
   return 1;
}

One workarround that i've found was to store the hInstance parameter received from DLLMain: extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) and inside DLL A when functions are called, I save current handle and set new handle the handle received from DllMain:

DLL A function1(............)
{
    HINSTANCE HinstanceOld = AfxGetResourceHandle(); 
    AfxSetResourceHandle(CErrohInstance); 
    .......
    //display dialog
    .....
    AfxSetResourceHandle(HinstanceOld);
}

By using this workarround It still causses assertion but the dialogs are shown.

What should be the normal way of solving this problem?


Solution

  • You have to insert the resources of the extension DLL into the resource chain of the regular DLL, not the EXE. Just create a function in the extension DLL and call it in the InitInstance method of the regular DLL, like this:

    void initDLL()
    {
      new CDynLinkLibrary(extensionDLL);
    }