DllMain

//////////////////////////////////////////////////////////////////////

#include <windows.h>

BOOL WINAPI DllMain(
  HINSTANCE hinstDLL,  // handle to DLL module
  DWORD fdwReason,     // reason for calling function
  LPVOID lpvReserved   // reserved
)
{
    switch(fdwReason)
 {
 case DLL_PROCESS_ATTACH:
  break;
 case DLL_THREAD_ATTACH:
  break;
 case DLL_THREAD_DETACH:
  break;
 case DLL_PROCESS_DETACH:
  break;
 }

    return TRUE;  //如果成功此处应该返回TRUE;
}

一、DLL_PROCESS_ATTACH
     当DLL被初次映射到进程的地址空间中时,系统将调用该DLL得DllMain函数,给它传    递参数fdwReason的值DLL_PROCESS_ATTACH.只有当DLL得文件映像初次被映射时,才会
  出现这种情况.   如果线程在后来为已经映射到进程的地址空间中的DLL被调用
  LoadLibaray(Ex)函数,那么操作系统只是递增DLL的使用计数,它并不再次调用          DLL_PROCESS_ATTACH的值来调用DLL的DllMain函数.
      当DllMain处理一个...ATTCH通知时,DllMain的返回值能够指明DLL的初始化是否
  已经取得成功.如果对heapCreate的调用取得成功,DllMain应该返回TRUE.
      如果fdwReason使用的是其他的值,那么系统将忽略DllMain返回的值.

二、DLL_PROCESS_DTTACH
     DLL从进程的地址空间中被卸载时,系统调用DLL的DllMain函数,给它传递fdwReason
   的值DLL_PROCESS_DTTACH.当DLL处理这个值时,它应该执行任何与进程相关的清除操   
 作.例如,DLL可以调用HeapDestroy函数来它之前撤销,它之前创建的堆栈.
       注意,如果DllMain函数接受到DLL_PROCESS_DETACH通时返回FALSE,那么DllMain
   就不是调用DLL_PROCESS_DETACH通知调用的.
       如果因为进程终止运行而使DLL被卸载,那么调用ExitProcess函数的线程将负责
   执行DllMain函数的代码.在正常情况下,这是应用程序的主线程.当你的进入点函数
   返回到C/C++运行期库的启动代码时,该代码将显示调用ExitProcess函数,终止进程
   的运行.
       如果因为进程中的线程调用FreeLibrary或FreeLibraryAndExitThread函数而将
    DLL卸载,那么调用函数的线程将负责执行DllMain函数的代码.如果使用FreeLibrary
    那么要等到DllMain函数完成对DLL_PROCESS_DETACH通知的执行后,该线程才对Free
    Library函数的调用中返回.
        注意,如果因为系统中的某个线程调用了TerminateProcess而使进程终止运行,
    那么系统将不调用带有DLL_PROCESS_DETACH值的DLL的DllMain函数.这意味着映射
    到进程地址空间中的任何DLL都没有机会在进程终止运行之前执行任何清除操作.
    这可能会导致数据的丢失.

三、DLL_THREAD_ATTACH
         当一个进程中创建线程时,系统要参看当前映射到该进程的地址空间中的所有
    Dll文件映像,并调用每个文件映像的带有...值的DllMain函数.这可以告诉所有的
    Dll执行每个线程的初始化操作.新创建的线程负责执行DLL的所有DllMain函数中的
    代码.只有当所有DLL都有机会处理该通知时,系统才允许新线程开始执行它的线程
    函数.
    !!!!!
         当一个新的DLL被映射到进程的地址空间中时,如果该进程内已经有若干个线程
   正在运行,那么系统将不为现有的线程调用带有...值的DLL的DllMain函数.只有当新
   线程创建时DLL被映射到进程的地址空间中,它才调用带有...值的DLL的DllMain函数.
   !!!!!!
  另外要注意,系统并不为进程的主线程调用带有...值的任何DllMain函数.进程
   初次启动时映射到进程的地址空间中的任何DLL均接受PROCESS_ATTCH通知,而不是...   通知.

四、DLL_THREAD_DETCH通知
 让线程终止运行的首先方法是使它的线程函数返回.这使得系统可以调用
    ExitThread函数注销该线程.此函数告诉系统,该线程要终止运行,但是系统并不立即
    将它撤销.相反,它要取出这个即将被撤销的线程,并让它调用已经映射的DLL的所有
    带有...值的DllMain函数.这个通知告诉所有的DLL执行每个线程的清除操作.
      注意,DLL能够防止线程终止运行.如果DllMain函数接受到...通知时,它就能够
    进入一个无限循环.只有当每个DLL已经完成对...通知的处理时,操作系统才会终止
    线程的运行.
 注意 如果因为系统中的线程调用TerminateThread函数而使该线程函数终止
    运行,那么系统将不调用...值的DLL的所有DllMain函数.这因为这映射到进程地址
    空间中的任何一个DLL都没有机会在线程终止运行之前执行任何清除操作.这可能导
    致数据的丢失.

顺序调用DllMain
 
 系统是顺序调用DLL的DllMain寒素的.为了理解这样做的意义,可以考虑下面
   这样一个环境.
 假设一个进程有两个线程,线程A和线程B.该进程还有一个DLL,称为SomeDLL.dll
   它被映射到了它的地址空间中.两个线程都准备调用CreateThread函数,以便再创建
   两个线程,即线程C和线程D.
 当线程A调用CreateThead来创建线程C时,系统会调用带有DLL_THREAD_ATTACH值    的SomeDLL.dll的DllMain函数.当线程C执行DllMain函数中的代码时,线程B调用         CreateThread函数来创建线程D.这时系统必须再次调用DLL_THREAD_ATTACH值的         DllMain函数这次是让线程D执行代码.
 但是,系统式顺序调用DllMain函数的,因此系统会暂停线程D的运行,直到线程
   C完成对DllMain函数中的代码的处理并且返回为止.
 当线程C完成DllMain的处理后,它就开始执行它的线程函数.这时系统唤醒线程
   D,让它处理DllMain中的代码.当它返回时,线程D开始处理它的线程函数.

 

你可能感兴趣的:(DllMain)