一、显式加载DLL模块使用函数 LoadLibrary/LoadLibraryEx

HINSTANCE LoadLibrary(PCTSTR pSzDLLPathName);

HINSTANCE LoadLibraryEx(
PCTSTR pSzDLLPathName,
HANDLE hF1le,
DWORD dwF1ags
);

pSzDLLPathName:加载的dll文件的路径。
hFile:保留供将来使用,现在是 NULL。
dwFlags:必须将它设置为 0 。或者设置 DONT_RESOLVE_DLL_REFERENCES、 LOAD_LIBRARY_AS_DATAFILE 和 LOAD_WITH_ALTERED_SEARCH_PATH 等标志的一个组合。

(1)DONT_RESOLVE_DLL_REFERENCES:标志使系统只需将 DLL 映射到调用进程的地址空间,而不用调用 DllMain(通常会调用)。

(2)LOAD_LIBRARY_AS_DATAFILE:系统只是将 DLL 映射到进程的地址空间中,就像它是数据文件一样。系统并不花费额外的时间来准备执行文件中的任何代码。如果不指定 LOAD_LIBRARY_AS_DATAFILE 标志,系统会认为需要执行文件中的代码,并用相应的方式来设置页面保护属性。例如使用此标志载入DLL,当对这个 DLL 调用 GetProcAddress 的时候,返回值会是 NULL,而 GetLastError 将会返回 ERROR_MOD_NOT_FOUND。

由于下面几个原因,该标志是非常有用的:

  • 加载只有资源没有函数的DLL时: 首先,如果有一个DLL(它只包含资源,但不包含函数),那么可以设定这个标志,使 DLL的文件映像能够映射到进程的地址空间中。
  • 调用加载资源的函数: 然后可以在调用加载资源的函数时,使用LoadLibraryEx函数返回的HINSTANCE值。
  • 加载EXE访问其中资源: 通常情况下,加载一个.exe文件,就能够启动一个新进程,但是也可以使用 LoadLibraryEx函数将.exe文件的映像映射到进程的地址空间中。借助映射的 .exe文件的HINSTANCE值,就能够访问文件中的资源。由于.exe文件没有DllMain函数,因此,当调用LoadLibraryEx来加载一个.exe文件时,必须设定 LOAD_LIBRARY_AS_DATAFILE 标志。

(3)LOAD_WITH_ALTERED_SEARCH_PATH:用于改变 LoadLibraryEx用来查找特定的DLL文件时使用的搜索算法。如果设定了该标志,那么LoadLibraryEx 函数就按照下面的顺序来搜索文件:

  • pszDLLPathName参数中设定的目录。
  • 进程的当前目录。
  • Windows的系统目录。
  • Windows目录。
  • PATH环境变量中列出的目录。

(4)LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE:与 LOAD_LIBRARY_AS_DATAFILE 相似,但是是以独占方式打开 DLL 文件,禁止任何其他程序在当前程序使用该 DLL 文件的时候对其修改。

(5)LOAD_LIBRARY_AS_IMAGE_RESOURCE:与 LOAD_LIBRARY_AS_DATAFILE 相似,但是载入 DLL 的时候,会对 RVA 进行修复(变成 RAW)。这样 RVA 可以直接使用,不必再根据 DLL 载入到的内存地址来对它们进行转换了。当需要对 DLL 进行解析来遍历 PE 段时,这个标志特别有用。


二、显式卸载DLL模块 FreeLibrary

BOOL FreeLibrary(HINSTANCE hinstD11);

也可以通过调用下面的函数从进程的地址空间中卸载 DLL,该函数是在Kernel32.dll中实现的:

VOID FreeLibraryAndExitThread(HINSTANCE hinstDll, DWORD dwExitCode);

微软创建 FreeLibraryAndExitThread 原因:

假定你要编写一个 DLL,当它被初次映射到进程的地址空间中时,该 D L L就创建一个线程。当该线程完成它的操作时,它通过调用FreeLibrary函数,从进程的地址空间中卸载该 DLL,并且终止运行,然后立即调用ExitThread。但是,如果线程分开调用 FreeLibrary和ExitThread,就会出现一个严重的问题。这个问题是调用FreeLibrary会立即从进程的地址空间中卸载 DLL。当调用的FreeLibrary返回时,包含对ExitThread调用的代码就不再可以使用(指DLL中函数的代码),因此线程将无法执行任何代码。这将导致访问违规,同时整个进程终止运行。

而使用此函数,FreeLibrary 返回时,下一条要执行的指令在 Kernel32.dll 中,可以继续调用 ExitThread。


关于 DLL 使用计数:只有使用计数递减至0,DLL才会从进程空间中撤销映像。

LoadLibrary和LoadLibraryEx 这两个函数用于对与特定的库相关的进程使用计数进行递增;
FreeLibrary和FreeLibraryAndExitThread这两个函数则用于对库的每个进程的使用计数进行递减。


其他函数

GetModuleHandle 函数可以根据名称返回加载的DLL的句柄(地址),当然也可以检查一个DLL是否被映射到进程的地址空间中。

GetModuleFileName 函数可以根据DLL句柄返回DLL完整路径。

20.1 DLL模块的显式加载和符号链接--《Windows核心编程》的更多相关文章

  1. dll显式加载与隐式加载

    使用动态DLL有两种方法,一种是隐式链接,一种是显式链接,如果用loadlibrary就是显示链接,用lib就属于隐式链接. 两种方法对于你的程序调用动态库时没有任何区别,只是你在编程时,步骤是不一样 ...

  2. DLL动态库的创建,隐式加载和显式加载

    动态库的创建 打开VS,创建如下控制台工程,工程命名为DllTest: 在弹出的对话框中选择"DLL"后单击"完成"按钮: 在工程中新建DllTest.h和Dl ...

  3. 《Entity Framework 6 Recipes》中文翻译系列 (28) ------ 第五章 加载实体和导航属性之测试实体是否加载与显式加载关联实体

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-11  测试实体引用或实体集合是否加载 问题 你想测试关联实体或实体集合是否已经 ...

  4. 【EF学习笔记08】----------加载关联表的数据 显式加载

    显式加载 讲解之前,先来看一下我们的数据库结构:班级表 学生表 加载从表集合类型 //显示加载 Console.WriteLine("=========查询集合===========&quo ...

  5. 【DLL】动态库的创建,隐式加载和显式加载(转)

    原文转自:https://blog.csdn.net/dcrmg/article/details/53437913

  6. Windows核心编程 第二十章 DLL的高级操作技术

    第2 0章 D L L的高级操作技术 看了下这章的内容,谈不上高级,都是些常用相关,但是还是有一些细节需要注意. 20.1 DLL模块的显式加载和符号链接 如果线程需要调用D L L模块中的函数,那么 ...

  7. 【windows核心编程】DLL相关(1)

    DLL相关的东西 1.DLL的加载方式 隐式: #pragma comment(lib, "XX.lib"); 编译器去查找名为XX.dll的DLL,除了名字相同,该DLL和该LI ...

  8. 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。

    windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...

  9. RequireJS 模块的定义与加载

    模块不同于传统的脚本文件,它良好地定义了一个作用域来避免全局名称空间污染.它可以显式地列出其依赖关系,并以函数(定义此模块的那个函数)参数的形式将这些依赖进行注入,而无需引用全局变量.RequireJ ...

  10. laravel 嵌套的渴求式加载

    今天在通过需求表A查询场地类型表B,然后通过表B的场地类型id去查询表C场地类型名的时候遇到了一个小的问题. 需求表A的字段:id.user_id .name等等: 中间表B的字段:id.appeal ...

随机推荐

  1. SpringBoot-mybatisplus-模糊查询

    模糊查询如何实现如下案例中两种实现方法 第一种:利用QueryWrapper.like自己实现. 第二种:使用@TableField(condition = SqlCondition.LIKE)实现. ...

  2. 机器学习笔记(二)使用paddlepaddle,再探波士顿房价预测

    目标 用paddlepaddle来重写之前那个手写的梯度下降方案,简化内容 流程 实际上就做了几个事: 数据准备:将一个批次的数据先转换成nparray格式,再转换成Tensor格式 前向计算:将一个 ...

  3. java进阶(20)--final/fianlly/fianlize区别

    1.final关键字.表示最终的.不变的 final修饰的类无法继承 final修饰的方法无法覆盖 final修饰的变量不能重新赋值 举例: final double weight; 2.finall ...

  4. Nginx IP地址较少时如何合理分配后端服务资源

    Nginx IP地址较少时如何合理分配后端服务资源 背景 客户系统很多时候会通过网闸或者是VPN登录到产品内 此时的IP地址一般是相同的. 这种情况下较难实现根据ip地址使用ip_hash的方式将压力 ...

  5. [转帖]signal 11 (SIGSEGV)错误排查

    https://www.jianshu.com/p/a4250c72d391 jni调试最蛋疼的就是signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault a ...

  6. [转帖]Nginx优化与防盗链

    目录 一.配置Nginx隐藏版本号 1.第一种方法修改配置文件 2.第二种方法修改源码文件,重新编译安装 二.修改Nginx用户与组 三.配置Nginx网页缓存时间 四.实现Nginx的日志分割 五. ...

  7. [转帖]Prometheus监控系统存储容量优化攻略,让你的数据安心保存!

    云原生监控领域不可撼动,Prometheus 是不是就没缺点?显然不是. 一个软件如果什么问题都想解决,就会导致什么问题都解决不好.所以Prometheus 也存在不足,广受诟病的问题就是 单机存储不 ...

  8. Oracle的awr的学习与整理

    Oracle的awr的学习与整理 背景 本来想上周末进行一下总结和汇总 因为周末两天进行了一次长时间的培训.所以没有成行. 只能在工作之余找时间进行总结. 数据库部分自己一个不是很强. 其实也比较抗拒 ...

  9. [转帖]linux下/proc/sysrq-trigger详解

    /proc/sysrq-trigger详解 这是一组"魔术组合键",只要内核没有被完全锁住,不管内核在做什么事情,使用这些组合键能即时打印出内核的信息. 使用SysRq组合键是了解 ...

  10. [转帖] mysql的timestamp会存在时区问题?

    我感觉 这样理解也有点不对 timestamp 应该是不带时区 只是 UTC1970-1-1 的时间戳 但是展示时会根据时区做一下计算 date time 就不会做转换而已.   原创:打码日记(微信 ...