windows DLL技术-DLL的入口点函数

news2024/10/23 8:01:20

DLL 可以选择指定入口点函数。 如果存在,则每当进程或线程加载或卸载 DLL 时,系统会调用入口点函数。 它可用于执行简单的初始化和清理任务。 例如,它可以在创建新线程时设置线程本地存储,并在线程终止时进行清理。

如果将 DLL 与 C 运行时库链接,它可能会提供入口点函数,并允许你提供单独的初始化函数。

如果要提供自己的入口点,可以声明DllMain 函数。 注意名称 DllMain 是用户定义的函数的占位符,必须指定生成 DLL 时使用的实际名称,这一点可以在编译器中指定,下面是某个DllMain的例子:

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpvReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
        
            if (lpvReserved != nullptr)
            {
                break; // do not do cleanup if process termination scenario
            }
            
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}
调用 DllMain 函数

每当发生以下任一事件时,系统都调用入口点函数:

  • 进程加载 DLL。 对于使用加载时动态链接的进程,DLL 在进程初始化期间加载。 对于使用运行时链接的进程,DLL 在 LoadLibrary 或 LoadLibraryEx 返回之前加载;
  • 进程卸载 DLL。 当进程终止或调用 FreeLibrary 函数且引用计数变为零时,将卸载 DLL。 如果进程由于 TerminateProcess 或 TerminateThread 函数而终止,则系统不会调用 DLL 入口点函数;
  • 在已加载 DLL 的进程中创建一个新线程。 可以使用 DisableThreadLibraryCalls 函数在创建线程时禁用通知;
  • 加载 DLL 的进程线程正常终止,不使用 TerminateThread 或 TerminateProcess。 当进程卸载 DLL 时,入口点函数仅为整个进程调用一次,而不是为进程的每个现有线程调用一次。 可以使用 DisableThreadLibraryCalls 在线程终止时禁用通知;

注意一次只能有一个线程可以调用入口点函数,这一点由windows系统保证。

系统在导致调用函数的进程或线程的上下文中调用入口点函数。 这允许 DLL 使用其入口点函数在调用进程的虚拟地址空间中分配内存,或打开进程可访问的句柄。 入口点函数还可以通过使用线程本地存储 (TLS) 为新线程分配专用的内存。 

DllMain 函数定义

必须使用标准调用调用约定声明 DLL 入口点函数。 如果未正确声明 DLL 入口点,则不会加载 DLL,并且系统会显示一条消息,指示必须使用 WINAPI 声明 DLL 入口点。

在函数主体中,可以处理调用 DLL 入口点的以下方案的任意组合:

  • 进程加载 DLL ;DLL_PROCESS_ATTACH
  • 当前进程创建新的线程;DLL_THREAD_ATTACH
  • 线程退出;DLL_THREAD_DETACH
  • 进程卸载 DLL ;DLL_PROCESS_DETACH

 入口点函数应仅执行简单的初始化任务。 它不得 调用 LoadLibrary 或 LoadLibraryEx 函数或调用这些函数的函数,因为这可能会在 DLL 加载顺序中创建依赖项循环。 这可能会导致在系统执行其初始化代码之前使用 DLL。 同样,入口点函数不得在进程终止期间 调用 FreeLibrary 函数或调用 FreeLibrary函数,因为这可能会导致在系统执行其终止代码后使用 DLL。

由于Kernel32.dll保证在调用入口点函数时加载到进程地址空间中,因此调用 Kernel32.dll 中的函数不会导致在执行其初始化代码之前使用 DLL。 因此,入口点函数可以创建 同步对象 (如关键部分和互斥体),并使用 TLS,因为这些函数位于Kernel32.dll。 例如,调用注册表函数是不安全的,因为它们位于 Advapi32.dll。

调用其他函数可能会导致难以诊断的问题。 例如,调用 User、Shell 和 COM 函数可能会导致访问冲突错误,因为其 DLL 中的某些函数调用 LoadLibrary 来加载其他系统组件。 相反,在终止期间调用这些函数可能会导致访问冲突错误,因为相应的组件可能已卸载或未初始化。

DllMain函数返回值

当由于加载进程而调用 DLL 入口点函数时,该函数返回 TRUE 以指示成功。 对于使用加载时链接的进程,返回值 FALSE 会导致进程初始化失败,并且进程终止。 对于使用运行时链接的进程,返回值 FALSE 会导致 LoadLibrary 或 LoadLibraryEx 函数返回 NULL,表示失败。 接下来windows系统使用 DLL_PROCESS_DETACH 立即调用入口点函数,并卸载 DLL。当出于任何其他原因调用该函数时,将忽略入口点函数的返回值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2221438.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【解决】使用Hypermark将Markdown文件转化为HTML文件

写在前面: 如果文章对你有帮助,记得点赞关注加收藏一波,利于以后需要的时候复习,多谢支持! 文章目录 一、文件准备(一)HTML模板文件(二)MD文件夹和储存文件夹 二、文件转…

【C++贪心】1536. 排布二进制网格的最少交换次数|1880

本文涉及知识点 C贪心 决策包容性 LeetCode1536. 排布二进制网格的最少交换次数 给你一个 n x n 的二进制网格 grid,每一次操作中,你可以选择网格的 相邻两行 进行交换。 一个符合要求的网格需要满足主对角线以上的格子全部都是 0 。 请你返回使网格满…

QUIC 启动!

掘金地址:https://juejin.cn/post/7428200842229006377 引言 QUIC是什么?明明你每天都在用,明明每天都在timing,难道你不知道吗?啊?不会吧,不会吧。 那就让本文来让你全方位的了解这个协议。 …

word表格跨页后自动生成的顶部横线【去除方法】

Hello World! Its been a long time. 这一年重心放在了科研、做事、追寻新的经历上,事有正事、琐事、幸事、哀事,内心与认知成长了一些,思想成熟了几分,技艺也有若干收获。不管怎样,来打个卡吧,纪念一下&…

爬虫日常实战

爬取美团新闻信息,此处采用两种方法实现: 注意点:因为此处的数据都是动态数据,所以一定要考虑好向下滑动数据包会更新的情况,不然就只能读取当前页即第一页数据,方法一通过更新ajax数据包网址页数&#xf…

【MyBatis】初识MyBatis 构建简单框架

目录 MyBatis前言搭建一个简单的MyBatis创建Maven项目引入必要依赖创建数据表结构创建User实体类创建Mapper接口Mapper层Dao层 创建MyBatis的Mapper映射文件编写测试类传统测试类JUnit测试 MyBatis 介绍:MyBatis是一款半自动的ORM持久层框架,具有较高的…

利用自定义 ref 实现函数防抖

今天来简单介绍一个新的方法,使用自定义 ref 实现函数防抖。 1. 自定义 ref 的来源 自定义 ref 防抖函数来自于前端开发中的两个概念:Vue 的响应式系统 和 数防抖(Debounce)。 1、Vue 响应式系统:Vue 提供了 ref 和…

Python学习的自我理解和想法(20)

#1024程序员节|征文# 学的是b站的课程(千锋教育),跟老师写程序,不是自创的代码! 今天是学Python的第20天,学的内容是面向对象中的私有属性,私有方法,多态,单例计模式。开…

【ubuntu18.04】ubuntu18.04升级cmake-3.29.8及还原系统自带cmake操作说明

参考链接 cmake升级、更新(ubuntu18.04)-CSDN博客 升级cmake操作说明 下载链接 Download CMake 下载版本 下载软件包 cmake-3.30.3-linux-x86_64.tar.gz 拷贝软件包到虚拟机 cp /var/run/vmblock-fuse/blockdir/jrY8KS/cmake-3.29.8-linux-x86_64…

spring源码中的,函数式接口,注解@FunctionalInterface

调用方 /org/springframework/beans/factory/support/AbstractBeanFactory.java:333sharedInstance getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It mi…

高级的SQL查询技巧有哪些?

成长路上不孤单😊😊😊😊😊😊 【14后😊///C爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于高级SQL查询技巧方面的相关内容&#xf…

MATLAB人脸考勤系统

MATLAB人脸考勤系统课题介绍 该课题为基于MATLAB平台的人脸识别系统。传统的人脸识别都是直接人头的比对,现实意义不大,没有一定的新意。该课题识别原理为:先采集待识别人员的人脸,进行训练,得到人脸特征值。测试的时…

HomeAssistant自定义组件学习-【一】

#环境准备# 按官方的步骤准备就可以,我是在Windows下使用VS Code开发的,安装了WSL(使用模板创建组件需要在WSL环境下完成) 官方链接:https://developers.home-assistant.io/docs/development_environment 环境准备好…

力扣困难题汇总(14道)

题4(困难): 思路: 找两数组中位数,这个看起来简单,顺手反应就是数第(mn)/2个,这个难在要求时间复杂度为log(mn),所以不能这样搞,我的思路是:每次切割长度为较…

【K8s】Kubernetes 词汇表

微思网络 厦门微思网络 K8S认证工程师(CKA)备考与学习指南https://mp.weixin.qq.com/s/XsEVpU7dKnJDBopynWW3GQ K8S-CKA课程试听:Container 概述 词汇表 此术语表旨在提供 Kubernetes 术语的完整、标准列表。其中包含特定于 Kubernetes 的技术术语以及…

uniapp修改input中placeholder样式

Uniapp官方提供了两种修改的属性方法&#xff0c;但经过测试&#xff0c;只有 placeholder-class 属性能够生效 <input placeholder"请输入手机验证码" placeholder-class"input-placeholder"/><!-- css --> <style lang"scss" s…

redis的zset实现下滑滚动分页查询思路

常规zset查询 我们redis的数据为 我们知道 我们常规查询的话 我们假如 zset 表中 有7个元素&#xff0c;然后我们进行分页查询的话&#xff0c;我们一次查3个元素&#xff0c;然后查出来元素 和元素的分数 我们redis的语法应该这样写 zrevrangebyscore wang 1000 0 withsc…

kotlin实现viewpager

说明:kotlin tablayout viewpager adapter实现滑动界面 效果图 step1: package com.example.flushfragmentdemoimport androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.fragment.app.Fragment import androidx.viewpager2.adapter.…

【uni-app学习-2】

一、跳转 方法&#xff1a;在methods中去定义方法&#xff1a; 上述为直接跳转&#xff0c;但是当你要跳转页面是由多个可切换页面组成比如&#xff1a; 这个页面其实是由两个页面组成&#xff0c;一个主页&#xff0c;一个我的&#xff0c;两个页面 路由配置需要用到toob…

java--多态(详解)

目录 一、概念二、多态实现的条件三、向上转型和向下转型3.1 向上转型3.2 向下转型 四、重写和重载五、理解多态5.1练习&#xff1a;5.2避免在构造方法中调用重写的方法&#xff1a; 欢迎来到权权的博客~欢迎大家对我的博客提出指导这是我的博客主页&#xff1a;点击 一、概念…