LoadLibrary函数详细说明

含义

将指定的模块加载到调用进程的地址空间中。指定的模块可能会导致其他模块被加载。对于其他加载选项,请使用 LoadLibraryEx函数。
使用语法
C ++

HMODULE WINAPI LoadLibrary(
  _In_ LPCTSTR lpFileName
);


参数

lpFileName [in]
模块的名称。这可以是库模块(.dll文件)或可执行模块(.exe文件)。指定的名称是模块的文件名,与模块定义(.def)文件中的LIBRARY关键字所指定的与库模块本身中存储的名称无关。
如果字符串指定完整路径,则该函数仅搜索该模块的路径。
如果字符串指定一个没有路径的模块名称或者相对路径,则该函数使用标准搜索策略来查找模块;
如果该功能找不到该模块,则该功能失败。指定路径时,一定要使用反斜杠(\),而不是正斜杠(/)。

如果字符串指定了没有路径的模块名称,并且省略了文件扩展名,则函数会将缺省库扩展名.dll附加到模块名称。要防止函数将.dll附加到模块名称,请在模块名称字符串中包含尾随点字符(.)。

返回值

  • 如果函数成功,则返回值是模块的句柄。

  • 如果函数失败,则返回值为NULL。要获得扩展错误信息,请调用 GetLastError。

备注

        要在DLL加载期间启用或禁用加载器显示的错误消息,请使用 SetErrorMode函数。
LoadLibrary可用于将库模块加载到进程的地址空间中,并返回可在GetProcAddress中使用的句柄 以获取DLL函数的地址。 LoadLibrary也可以用来加载其他可执行模块。例如,该函数可以指定一个.exe文件来获取可以在FindResource或 LoadResource中使用的 句柄。但是,不要使用 LoadLibrary运行.exe文件。而是使用CreateProcess函数。

如果指定的模块是一个尚未为调用进程加载的DLL,则系统将使用DLL_PROCESS_ATTACH值调用DLL的DllMain函数 。如果 DllMain返回TRUE,则 LoadLibrary将返回模块的句柄。如果 DllMain返回FALSE,则系统从进程地址空间卸载DLL,并且 LoadLibrary返回NULL。

        模块句柄不是全局的或可继承的。一个进程调用 LoadLibrary不会产生另一个进程可以使用的句柄 - 例如,调用 GetProcAddress。在调用GetProcAddress之前 ,另一个进程必须自己调用LoadLibrary。
        如果lpFileName不包含路径,并且有多个具有相同基本名称和扩展名的已加载模块,则该函数将返回首先加载的模块的句柄。
如果在lpFileName参数中未指定文件扩展名,则会附加默认库扩展名.dll。但是,文件名称字符串可以包含尾随点字符(.),以指示模块名称没有扩展名。当没有指定路径时,函数搜索加载的模块,其基本名称与要加载的模块的基本名称相匹配。如果名称匹配,则加载成功。否则,该功能将搜索该文件。
        搜索到的第一个目录是包含用于创建调用过程的映像文件的目录(有关更多信息,请参阅 CreateProcess函数)。这样做可以在不将进程的安装目录添加到PATH环境变量的情况下找到与进程关联的私有动态链接库(DLL)文件。如果指定了相对路径,则整个相对路径将附加到DLL搜索路径列表中的每个标记。要从相对路径加载模块而不搜索任何其他路径,请使用GetFullPathName获取非相对路径,并使用 非相对路径调用 LoadLibrary。有关DLL搜索顺序的更多信息,请参阅 动态链接库搜索顺序。
搜索路径可以使用SetDllDirectory函数进行更改 。建议使用此解决方案,而不是使用SetCurrentDirectory或硬编码DLL的完整路径。
如果指定了路径并且存在应用程序的重定向文件,则该函数将搜索应用程序目录中的模块。如果模块存在于应用程序的目录中,则 LoadLibrary将忽略指定的路径并从应用程序的目录加载该模块。如果模块不在应用程序的目录中,则 LoadLibrary将从指定的目录加载模块。有关更多信息,请参阅 动态链接库重定向。
如果使用程序集名称调用LoadLibrary而不指定路径,并且程序集列在系统兼容清单中,则调用会自动重定向到并行程序集。
系统在所有加载的模块上维护每个进程的引用计数。调用LoadLibrary会 增加引用计数。调用FreeLibrary或 FreeLibraryAndExitThread函数会减少引用计数。系统在其引用计数达到零或过程终止时(不管引用计数是多少)卸载模块。
Windows Server 2003和Windows XP:   Visual C ++编译器支持使您能够声明线程局部变量的语法: _declspec(thread)。如果在DLL中使用此语法,则无法在Windows Vista之前的Windows版本上使用LoadLibrary显式加载DLL 。如果您的DLL将被显式加载,则必须使用线程本地存储函数而不是_declspec(thread)。有关示例,请参阅 动态链接库中的使用线程本地存储。
安全备注
不要使用SearchPath函数为后续的LoadLibrary调用检索DLL的路径。该 SearchPath中的功能比使用不同的搜索顺序 调用LoadLibrary和不使用过程中的安全搜索模式,除非明确调用启用 SetSearchPathMode与 BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE。因此, SearchPath可能首先搜索用户的当前工作目录中指定的DLL。如果攻击者已经将恶意版本的DLL复制到当前工作目录中,则SearchPath将检索到该路径会指向恶意的DLL,LoadLibrary将会加载。

不要根据搜索DLL 的LoadLibrary调用对操作系统版本进行假设 。如果应用程序运行在DLL合法不存在,但恶意版本的DLL在搜索路径中的环境中,则可能会加载DLL的恶意版本。


最小支持的客户端
Windows XP [仅适用于桌面应用程序]
最低支持的服务器
Windows Server 2003 [仅适用于桌面应用程序]

Winbase.h(包括Windows.h)

KERNEL32.LIB
DLL
KERNEL32.DLL
Unicode和ANSI名称
LoadLibraryW(Unicode)和LoadLibraryA(ANSI)

  • 15
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
实验准备: 1. Visual Studio 2019 2. Windows操作系统 实验步骤: 1. 创建一个动态链接库项目 打开Visual Studio,选择File->New->Project,在弹出的对话框中选择Visual C++->Windows Desktop->Windows Desktop Wizard,然后选择DLL(动态链接库)项目类型。 2. 编写动态链接库函数 在项目中添加一个C++源文件(.cpp),编写一个简单的函数。例如,以下是一个计算两个整数之和的函数: ```c++ #include <iostream> extern "C" __declspec(dllexport) int add(int a, int b) { std::cout << "Calling add() function in DLL..." << std::endl; return a + b; } ``` 这个函数使用了`extern "C"`来指定C语言风格的函数名,以便在动态链接库中正确导出函数。`__declspec(dllexport)`用于指定函数是导出函数。 3. 生成动态链接库 在Visual Studio中,选择Build->Build Solution,生成动态链接库文件(.dll)和相关的库文件(.lib)。 4. 查看导入导出函数 使用DumpBin.exe工具查看导入导出函数。在Visual Studio命令提示符中,输入以下命令: ``` dumpbin /exports yourdll.dll ``` 其中`yourdll.dll`是你创建的动态链接库文件名。将会输出类似以下的内容: ``` ordinal hint RVA name 1 0 00001000 add ``` 其中`add`就是我们刚刚编写的导出函数。 5. 创建新程序并调用动态链接库函数 创建一个新的控制台应用程序,在其中调用动态链接库中的函数。以下是一个简单的例子: ```c++ #include <iostream> #include <Windows.h> typedef int (*AddFunc)(int, int); int main() { HMODULE dllHandle = LoadLibrary("yourdll.dll"); if (dllHandle == NULL) { std::cout << "Failed to load DLL!" << std::endl; return 1; } AddFunc add = (AddFunc)GetProcAddress(dllHandle, "add"); if (add == NULL) { std::cout << "Failed to get function address!" << std::endl; return 1; } std::cout << "Calling add() function in DLL..." << std::endl; int result = add(1, 2); std::cout << "Result: " << result << std::endl; FreeLibrary(dllHandle); return 0; } ``` 在这个例子中,我们使用`LoadLibrary`函数加载动态链接库文件,并使用`GetProcAddress`函数获取导出函数的地址。然后我们就可以像调用普通函数一样调用动态链接库中的函数了。 6. 运行程序并查看结果 编译并运行新程序,将会输出以下内容: ``` Calling add() function in DLL... Result: 3 ``` 这表明我们成功地调用了动态链接库中的函数,并获得了正确的结果。 实验总结: 本次实验我们学习了如何创建和使用动态链接库。动态链接库可以将代码和数据封装成一个可重用的模块,以便在不同的程序中调用。我们还学习了如何使用DumpBin.exe工具查看动态链接库中的导入导出函数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道格拉斯范朋克

播种花生牛奶自留田

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值