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

来源:互联网 发布:python自动化运维意义 编辑:程序博客网 时间:2024/05/23 19:29


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.
Back to the top

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