How to Provide Your Own DllMain in an MFC Regular DLLID: Q148791
|
By design, MFC Regular DLLs have a default DllMain function provided
automatically by MFC. Regular DLLs should not provide their own DllMain.
Any initialization which is necessary when the DLL is loaded should be done
in the InitInstance member function of the one CWinApp-derived class in the
Regular DLL. Deinitialization and termination code should go in the
ExitInstance member function.
However, InitInstance is only called by MFC's DllMain when a process
attaches (DLL_PROCESS_ATTACH) to the DLL and ExitInstance is called only
when a process detaches (DLL_PROCESS_DETACH) from the DLL. If it is
necessary to handle thread attachment to and detachment from
(DLL_THREAD_ATTACH and DLL_THREAD_DETACH) in MFC Regular DLL, the Regular
DLL will need to provide its own DllMain. This article explains how to do
it.
When a Regular DLL is created, the MFC source forcibly links in the code
for the source file \Msdev\Mfc\Src\Dllmodul.cpp. Dllmodul.cpp contains most
of the code added to a Regular DLL to support MFC in that DLL. One of the
most important functions in Dllmodul.cpp is the DllMain function.
To add code to MFC's DllMain, copy the \Msdev\Mfc\Src\Dllmodul.cpp source
file to your project directory, and include the copy in your project. This
copy of Dllmodul.cpp will be compiled and linked into your DLL instead of
the Dllmodul.cpp in the Mfc\Src directory, so changes to the DllMain in it
will show up in the final DLL.
The primary caveat is that this is not a recommended solution and should
only be used when absolutely necessary. Any changes to the code in
Dllmodul.cpp will undoubtedly have unpredictable results. Add code only, do
not remove or modify the existing code.
For regular DLLs that use MFC in the Shared Lib, the module state should be
set at the beginning of any added code and restored before returning from
DllMain. Refer to the sample code in this article for an example of a
DllMain that handles the DLL_THREAD_ATTACH and DLL_THREAD_DETACH
notifications and properly switches the module state as necessary.
Additional care must be taken when relying on DllMain being called with
DLL_THREAD_ATTACH and DLL_THREAD_DETACH because of the following
conditions:
////////////////////////////////////////////////////////////////////
// export DllMain for the DLL
// Add code in the specified sections only.
// Remove code at your own risk.
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID
/*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
// ... Code abbreviated from DLLMODUL.CPP
}
else if (dwReason == DLL_PROCESS_DETACH)
{
// ... Code abbreviated from DLLMODUL.CPP
}
// NEW CODE ADDED HERE
// -------------------
else if (dwReason == DLL_THREAD_ATTACH)
{
#ifdef _AFXDLL
// set module state
ASSERT(AfxGetThreadState()->m_pPrevModuleState == NULL);
AfxGetThreadState()->m_pPrevModuleState =
AfxSetModuleState(AfxGetStaticModuleState());
#endif
// ADD DLL_THREAD_ATTACH CODE HERE
// Remember that this won't necessarily be called for
// every thread in the process into which this DLL is mapped
// Threads created by the process BEFORE the DLL
// was loaded will not call into DLL_THREAD_ATTACH.
#ifdef _AFXDLL
// restore previously-saved module state
VERIFY(AfxSetModuleState(AfxGetThreadState()->m_pPrevModuleState)
== AfxGetStaticModuleState());
DEBUG_ONLY(AfxGetThreadState()->m_pPrevModuleState = NULL);
#endif
}
else if (dwReason ==DLL_THREAD_DETACH)
{
#ifdef _AFXDLL
// set module state
ASSERT(AfxGetThreadState()->m_pPrevModuleState == NULL);
AfxGetThreadState()->m_pPrevModuleState =
AfxSetModuleState(AfxGetStaticModuleState());
#endif
// ADD DLL_THREAD_DETACH CODE HERE
#ifdef _AFXDLL
// restore previously-saved module state
VERIFY(AfxSetModuleState(AfxGetThreadState()->m_pPrevModuleState)
== AfxGetStaticModuleState());
DEBUG_ONLY(AfxGetThreadState()->m_pPrevModuleState = NULL);
#endif
}
return TRUE;
}
For more information on MFC objects being thread local, please see the following article in the Microsoft Knowledge Base:
Q147578 CWnd Derived MFC Objects and Multi-threaded ApplicationsFor more information on module state information, please see the following article in the Microsoft Knowledge Base:
Q140850 How to Convert DLLTRACE to Use MFC in Shared LibraryFor more information on why you shouldn't create a thread in DllMain, please see the following article in the Microsoft Knowledge Base:
Q142243 PRB: Cannot Create an MFC Thread During DLL Startup
Additional query words: DllMain DLL_THREAD_ATTACH DLL_THREAD_DETACH DLLMODUL.CPP RegDLL 4.00
Keywords : kbcode kbDLL kbMFC kbVC
Version : 4.00
Platform : NT WINDOWS
Issue type :
Last Reviewed: July 26, 1999