【VB技巧】VB DllMain DLL的进入,退出函数详解

admin 2021年4月3日19:01:10评论68 views字数 5140阅读17分8秒阅读模式

    VB DllMain DLL的进入、退出函数详解,VB DllMain DLL的进入、退出函数,VB DllMain DLL的进入、退出详解,VB DllMain DLL的进入函数详解,VB DllMain DLL的退出函数详解,VB DllMain DLL进入函数详解,VB DllMain DLL退出函数详解,VB DllMain DLL进入函数,VB DllMain DLL退出函数,VB DllMain DLL函数详解,VB DllMain DLL函数,VB DllMain函数,VB DllMain DLL,Dll入口点函数,VB DllMain,DllMain 简介,WinMain 入口函数,DLL入口函数,DllMain 入口函数,Const DLL_PROCESS_ATTACH As Long = 1 '当DLL被映射到进程的地址空间时,Const DLL_PROCESS_DETACH As Long = 0 '当DLL被从进程的地址空间解除映射时,Const DLL_THREAD_ATTACH As Long = 2 '当进程创建一线程时,Const DLL_THREAD_DETACH As Long = 3 '当线程调用了 ExitThread 结束线程时,DLL_PROCESS_ATTACH,DLL_PROCESS_DETACH,DLL_THREAD_ATTACH,DLL_THREAD_DETACH,系统调用 DllMain 函数的四种情况,DllMain(ByVal hinstDLL As Long, ByVal fdwReason As Long, ByVal lpvReserved As Long) As Long。

VB DllMain DLL的进入、退出函数详解:

DllMain 简介:

    跟 exe 有个 main 或者 WinMain 入口函数一样,DLL 也有一个入口函数,就是 DllMain。以“DllMain”为关键字,来看看MSDN帮助文档怎么介绍这个函数的。

  The DllMain function is an optional method of entry into a dynamic-link library (DLL)。

    简要翻译:对于动态链接库,DllMain是一个可选的入口函数。

    这句话很重要,很多初学者可能都认为一个动态链接库肯定要有 DllMain 函数。其实不然,像很多仅仅包含资源信息的 DLL 是没有 DllMain 函数的。

系统调用 DllMain 函数的四种情况:

    当一个进程载入或卸载一个DLL时,DLLMAIN会被调用(DLLMAIN获得DLL_PROCESS_ATTACH消息),线程也是一样(获得DLL_THREAD_ATTACH消息)。

    在静态链接时,或动态链接时调用 LoadLibrary 和 FreeLibrary 都会调用 DllMain 函数。DllMain 的第三个参数 fdwReason 指明了系统调用 dll 的原因,它可能是:

    Const DLL_PROCESS_ATTACH  As Long = 1      '当DLL被映射到进程的地址空间时
    Const DLL_PROCESS_DETACH  As Long = 0      '当DLL被从进程的地址空间解除映射时
    Const DLL_THREAD_ATTACH   As Long = 2      '当进程创建一线程时
    Const DLL_THREAD_DETACH   As Long = 3      '当线程调用了 ExitThread 结束线程时

  以下从这四种情况来分析系统何时调用了DllMain。

DLL_PROCESS_ATTACH:

    当一个程序要调用 Dll 里的函数,首先要先把 DLL 文件映射到进程的地址空间。要把一个 DLL 文件映射到进程的地址空间,有两种方法:静态链接和动态链接的 LoadLibrary 或者 LoadLibraryEx。

  当一个 DLL 文件被映射到进程的地址空间时,系统调用该 DLL 的 DllMain 函数,传递的 fdwReason 参数为 DLL_PROCESS_ATTACH。这种调用只会发生在第一次映射时。如果同一个进程后来为已经映射进来的 DLL 再次调用 LoadLibrary 或者 LoadLibraryEx,操作系统只会增加 DLL 的使用次数,它不会再用 DLL_PROCESS_ATTACH 调用 DLL 的 DllMain 函数。不同进程用 LoadLibrary 同一个 DLL 时,每个进程的第一次映射都会用 DLL_PROCESS_ATTACH 调用 DLL 的 DllMain 函数。

  可参考 DllMainTest 的 DLL_PROCESS_ATTACH_Test 函数。

DLL_PROCESS_DETACH:

  当 DLL 被从进程的地址空间解除映射时,系统调用了它的 DLLMain,传递的fdwReason值是 DLL_PROCESS_DETACH。当 DLL 处理该值时,它应该执行进程相关的清理工作。   那么什么时候 DLL 被从进程的地址空间解除映射呢?两种情况:

  ◆FreeLibrary 解除 DLL 映射(有几个 LoadLibrary,就要有几个 FreeLibrary)
  ◆进程结束而解除 DLL 映射,在进程结束前还没有解除 DLL 的映射,进程结束后会解除 DLL 映射。(如果进程的终结是因为调用了 TerminateProcess,系统就不会用 DLL_PROCESS_DETACH 来调用 DLL 的 DllMain 函数。这就意味着 DLL 在进程结束前没有机会执行任何清理工作。)

  注意:当用 DLL_PROCESS_ATTACH 调用 DLL 的 DllMain 函数时,如果返回 FALSE,说明没有初始化成功,系统仍会用 DLL_PROCESS_DETACH 调用 DLL 的 DllMain 函数。因此,必须确保清理那些没有成功初始化的东西。

  可参考 DllMainTest 的 DLL_PROCESS_DETACH_Test 函数。

DLL_THREAD_ATTACH:

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

  新创建的线程负责执行这次的 DLL 的 DllMain 函数,只有当所有的 DLL 都处理完这一通知后,系统才允许进程开始执行它的线程函数。

  注意跟 DLL_PROCESS_ATTACH 的区别,我们在前面说过,第 n(n>=2) 次以后把 DLL 映像文件映射到进程的地址空间时,是不再用 DLL_PROCESS_ATTACH 调用 DllMain 的。而 DLL_THREAD_ATTACH 不同,进程中的每次建立线程,都会用值 DLL_THREAD_ATTACH 调用 DllMain 函数,哪怕是线程中建立线程也一样。

DLL_THREAD_DETACH:

  如果线程调用了 ExitThread 来结束线程(线程函数返回时,系统也会自动调用 ExitThread),系统查看当前映射到进程空间中的所有 DLL 文件映像,并用 DLL_THREAD_DETACH 来调用 DllMain 函数,通知所有的 DLL 去执行线程级的清理工作。

  注意:如果线程的结束是因为系统中的一个线程调用了 TerminateThread,系统就不会用值 DLL_THREAD_DETACH 来调用所有 DLL 的 DllMain 函数。

DllMain 函数换名:

  在早期的 SDK 版本中,DllMain 是叫做 DllEntryPoint。其实有一件鲜为人知的事:一个 Dll 的入口函数名是可以自己定义的。下面我将以 VC++6.0 为例来演示如何更改。首先要说明一点,虽然 DllMain 可以换成其他函数名,但函数的参数和返回值必须和 DllMain 一样。而且这个函数要为 __stdcall 类型(DllMain 本身也是 __stdcall 类型)。

  打开 VC++ 菜单 ProjectSettingsLink tab Output in the Category box,在 Entry-point symbol 中输入要替换 DllMain 的函数名(当然这个函数名是你程序中已经实现的函数)。Entry-point symbol 是干么的呢?可以以关键字“Entry-point symbol”搜索 MSDN 帮助文档查看,搜索时,打钩“仅搜索标题”会更快定位。

    按OK后,如果马上编译的话会出现如下错误:

    LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main

    Debug/Dll.dll : fatal error LNK1120: 1 unresolved externals

    打开 VC++ 菜单 ProjectSettingsC/C++ 选项卡,在 Project Options:末尾的地方添加“/D”,要注意位置(/GZ 之前),我试了,要把 /D 放到 /GZ 后面也会链接错误,我也不懂为什么。按OK,再次编译,成功。大家可以自己测试下到底有没有更改成功,什么,如果测试?打出调式信息啊。

    DisableThreadLibraryCalls,看帮助就知道它是干么用的:The DisableThreadLibraryCalls function disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the dynamic-link library (DLL) specified by hLibModule. This can reduce the size of the working code set for some applications.

    翻译:DisableThreadLibraryCalls 函数禁止动态链接库(DLL)中 hLibModule 的 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知消息,这样可以减少一些应用程序工作代码的大小。

VB DllMain 函数示例:
    '系统调用 DllMain 函数的四种情况
    '当一个进程载入或卸载一个DLL时,DLLMAIN会被调用(DLLMAIN获得DLL_PROCESS_ATTACH消息),线程也是一样(获得DLL_THREAD_ATTACH消息)

    Const DLL_PROCESS_ATTACH  As Long = 1                                           '当DLL被映射到进程的地址空间时
    Const DLL_PROCESS_DETACH  As Long = 0                                           '当DLL被从进程的地址空间解除映射时
    Const DLL_THREAD_ATTACH   As Long = 2                                           '当进程创建一线程时
    Const DLL_THREAD_DETACH   As Long = 3                                           '当线程调用了 ExitThread 结束线程时

    Public Function DllMain(ByVal hinstDLL As Long, ByVal fdwReason As Long, ByVal lpvReserved As Long) As Long 'Dll入口点函数
        Select Case fdwReason
            Case DLL_PROCESS_ATTACH
                '当DLL被映射到进程的地址空间时
            Case DLL_PROCESS_DETACH
                '当DLL被从进程的地址空间解除映射时
            Case DLL_THREAD_ATTACH
                '当进程创建一线程时
            Case DLL_THREAD_DETACH
                '当线程调用了 ExitThread 结束线程时
        End Select
        DllMain = 1
    End Function  

文章来源于lcx.cc:【VB技巧】VB DllMain DLL的进入,退出函数详解

相关推荐: 本站全面改版,系统升级到 Nuclear-Blog v5.0!

21 - Daft Punk - TRON Legacy (End Titles)     忙活了两三天,完全重新设计、写了模板,如你现在所看到的界面,黑白清爽模板,以黑色和白色为主色调,整体感觉清新、简单。以及修复了一些安全问题,和其他的之类的,不一一列举了…

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年4月3日19:01:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【VB技巧】VB DllMain DLL的进入,退出函数详解https://cn-sec.com/archives/319616.html

发表评论

匿名网友 填写信息