像所有进程都有一个入口点函数一样,DLL也有一个入口点函数--DllMain。系统在不同的时间调用这个入口点函数,通常用于供DLL进行每个进程或线程的初始化和清除操作。这四个不同时刻分别为DLL_PROCESS_ATTACH、DLL_PROCESS_DETACH、DLL_TREAD_ATTACH、DLL_TREAD_DETACH。下面进行分别描述

    当DLL被初次映射到进程的地址空间中时,系统将调用该DLL的DllMain,给它传递fdwReason参数的值DLL_PROCESS_ATTACH。注意:1、只有在DLL_PROCESS_ATTACH时,系统会关注DllMain函数的返回值,其他时刻忽略。2、只有DLL文件映像被初次映射时,才会调该DllMain。调用过程:第一步、.exe文件映像和DLL映像被同时映射到一个进程地址空间中。第二步、系统调用DllMain,给fdwReason参数传递DLL_PROCESS_ATTACH。第三、系统根据调用DllMain的返回值,TRUE-继续.exe模块的入口点函数;FALSE-初始化失败,系统终止整个进程的运行,从它的进程空间删除所有文件映像,给用户调出一个对话框。这里显示调用DLL和隐式调用稍有区别。显示调用,系统使用Loadlibrary(Ex)线程,调用DllMain,当DllMain函数处理了DLL_PROCESS_ATTACH通知时,系统便允许调用的Loadlibrary(Ex)函数返回。如果DllMain函数返回FLASE,指明初始化没有取得成功,系统从进程空间中卸载DLL文件映像,而对Loadlibrary的调用返回NULL。

    当DLL从进程的地址空间中被卸载时,系统将调用该DLL的DllMain,给它传递fdwReason参数的值DLL_PROCESS_DETACH。这里只注意三点:1、DLL能够阻止进程终止运行。只有当每个DLL都已完成对DLL_PROCESS_DETACH的处理时,操作系统才会终止进程的运行。2、如果系统中的某个线程调用了TerminateProcess而使进程终止运行,那么系统将不会调用带有DLL_PROCESS_DETACH值的DLL的DllMain函数。这样映射到进程的地址空间中的任何DLL都没有机会执行任何清除操作。

    当在一个进程中创建线程时,系统要查看当前映射到该进程的地址空间中的所有DLL文件映像,并调用每个文件映像的带有DLL_THREAD_ATTACH值的DllMain函数。