现在的位置: 首页 > 综合 > 正文

HOWTO: How to Provide Your Own DllMain in an MFC Regular DLL

2013年03月27日 ⁄ 综合 ⁄ 共 3319字 ⁄ 字号 评论关闭


http://support.microsoft.com/kb/148791/en-us

Additional care must be taken when relying on DllMain being called with DLL_THREAD_ATTACH and DLL_THREAD_DETACH because of the following conditions: 


  • When a thread is created in a process, the system calls DllMain with a value of DLL_THREAD_ATTACH for each of the DLLs mapped into into the process. However, if a process has several threads running in it when a new DLL is mapped
    into it, DllMain isn't called with a DLL_THREAD_ATTACH value for any of the existing threads.
  • 不会因为进程中已有的线程调用DLL_THREAD_ATTACH 
  • DllMain is not called with a value DLL_THREAD_ATTACH for the process's primary thread.
  • 进程的主线程不调用DLL_THREAD_ATTACH 
  • On thread termination (by a call to ExitThread), DllMain is called with a value of DLL_THREAD_DETACH for each of the DLLs. DllMain is not called with DLL_THREAD_DETACH for any thread unless a thread terminates by calling ExitThread.
  • 线程以ExitThread结束,不调用DLL_THREAD_DETACH 
  • If a thread terminates due to a call to TerminateThread, DllMain isn't called with a value DLL_THREAD_DETACH.
  • 线程以TerminateThread结束,不调用DLL_THREAD_DETACH 
  • It is possible for a thread in a process to call LoadLibrary to load a DLL causing a call to DllMain with DLL_PROCESS_ATTACH, and then on thread termination, cause a call to dllMain with DLL_THREAD_DETACH without ever calling DLL_THREAD_ATTACH.
    It is therefore best that the thread that calls LoadLibrary also call FreeLibrary.
  • 如果非主线程调用LoadLibrary ,FreeLibrary,则DLL_PROCESS_ATTACH,DLL_THREAD_DETACH ,而没有DLL_THREAD_ATTACH

NOTE: MFC CWnd objects, CDC objects, CMenu objects, GDI objects, and CImageList objects are restricted to a per-thread, per-module basis. In other words, MFC objects created in one module or thread cannot be passed to and/or used in a different module or thread.
This has special relevance for any code added to handle DLL_THREAD_ATTACH or DLL_THREAD_DETACH in DllMain because DllMain is called for these reasons with different threads. CWnd objects, for instance, created in DllMain during DLL_PROCESS_ATTACH or in InitInstance
will not be valid during DLL_THREAD_ATTACH.

Sample Code

//////////////////////////////////////////////////////////////////// 
// 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;
}
				

抱歉!评论已关闭.