DLL相关的东西

1、DLL的加载方式

隐式:

#pragma comment(lib, "XX.lib");

编译器去查找名为XX.dll的DLL,除了名字相同,该DLL和该LIB的GUID也相同。

显式:

HINSTANCE   hInst = LoadLibrary(TEXT("XX.dll"));

if(NULL == hInst)  retrun;

HINSTANCE hInst = LoadLibrary(TEXT("XX.dll"), NULL,   FLAGS);

第三个参数为一些标志,详见核心编程。

2、DLL的入口函数

原型

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
);

其中hModule为该DLL在当前进程地址空间中的位置,ul_reason_for_call为调用此函数的原因,lpReserved如果为显式加载则为0,如果为隐式加载则为非0。

详细说一下ul_reason_for_call

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
#ifdef _DEBUG switch (ul_reason_for_call)
{
//只在该DLL第一次加载进地址空间的时候被调用一次
//此后当该DLL被加载进不同进程的地址空间时让然不调用
//当主调线程通过该reason调用DllMain函数时,主调线程不会收到DLL_THREAD_ATTACH通知
case DLL_PROCESS_ATTACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_PROCESS_ATTACH ***********\r\n"));
break; //当该DLL已经被加载到进程地址空间后,当有新【线程创建】的时候,新创建的线程先执行此段代码
//然后再去执行线程本身的代码
//不管有几个DLL,每个DLL的此处代码都会被新线程执行
case DLL_THREAD_ATTACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_THREAD_ATTACH ***********\r\n"));
break; //当该DLL已经被加载到进程地址空间后,当有【线程结束】的时候,该线程结束之前会调用此处代码
//然后才返回
//不管有几个DLL,每个DLL的此处代码都会被执行
case DLL_THREAD_DETACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_THREAD_DETACH *********** \r\n"));
break; //只有在该DLL从内存中卸载的时候才会被调用一次
case DLL_PROCESS_DETACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_PROCESS_DETACH ***********\r\n"));
break;
} #endif return TRUE;
}

demo

有两个DLL, ADll.dll 和 BDll.dll

在程序中加载这个两个DLL, 然后创建一个新线程,看输出

//加载DLL
void CUseABDllDlg::OnBnClickedBtnLoadlib()
{
HINSTANCE hInstA = LoadLibrary(_T("ADll.dll"));
HINSTANCE HIntB = LoadLibrary(_T("BDll.dll"));
if (NULL == hInstA || NULL == HIntB)
{
AfxMessageBox(_T("加载DLL失败"));
return;
}
} //线程函数
UINT WINAPI WorkThread(LPVOID lpParam)
{
#ifdef _DEBUG
OutputDebugString(TEXT("\r\n&&&&&&&&&&&&&&&&&&线程被创建&&&&&&&&&&&&&&&&&\r\n"));
#endif return 0U;
} //创建线程
void CUseABDllDlg::OnBnClickedButton2()
{
HANDLE hThread = (HANDLE)_beginthreadex(NULL, , WorkThread, NULL, , NULL);
if (NULL == hThread || INVALID_HANDLE_VALUE == hThread)
{
AfxMessageBox(_T("创建线程失败"));
}
}

输出

结论:

每创建一个新线程,当前进程地址空间中的DLL的DllMain函数都会通过DLL_THREAD_ATTACH通知被调用一次

每结束一个线程,进程地址空间空的DLL的DllMain函数都会通过DLL_THREAD_DETACH通知被调用一次。

【windows核心编程】DLL相关(1)的更多相关文章

  1. windows核心编程 DLL技术 【转】

    注:本文章转载于网络,源地址为:http://blog.csdn.net/ithzhang/article/details/7051558 本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑 ...

  2. 《Windows核心编程系列》二十谈谈DLL高级技术

    本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑定的技术. 第一种将DLL映射到进程地址空间的方式是直接在源代码中引用DLL中所包含的函数或是变量,DLL在程序运行后由加载程序隐式的载入, ...

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

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

  4. 《windows核心编程系列》十七谈谈dll

    DLL全称dynamic linking library.即动态链接库.广泛应用与windows及其他系统中.因此对dll的深刻了解,对计算机软件开发专业人员来说非常重要. windows中所有API ...

  5. 《Windows核心编程》读书笔记 上

    [C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...

  6. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  7. 【转】《windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  8. 《windows核心编程系列》二十一谈谈基址重定位和模块绑定

    每个DLL和可执行文件都有一个首选基地址.它表示该模块被映射到进程地址空间时最佳的内存地址.在构建可执行文件时,默认情况下链接器会将它的首选基地址设为0x400000.对于DLL来说,链接器会将它的首 ...

  9. 《windows核心编程系列》十六谈谈内存映射文件

    内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件.将文件映射到内存中后,我们就可以在内存中操作他们了 ...

  10. windows核心编程 - 线程同步机制

    线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...

随机推荐

  1. sudo: /etc/sudoers 的模式为 0551,应为 0440

    环境:Ubuntu 12.04.4 LTS 32bit 本想修改/etc/sudoers文件,取消sudo权限的密码.但是因为sudoers文件无‘w’(写)的权限,然后用命令加写权限的时候加错了,加 ...

  2. Linux中断处理体系结构分析

    Linux中断处理体系结构分析(一) 异常,就是可以打断CPU正常运行流程的一些事情,比如外部中断.未定义指令.试图修改只读的数据.执行swi指令(Software Interrupt Instruc ...

  3. 从一点儿不会开始——Unity3D游戏开发学习(二) ——GUI控件之Button

    一些废话 我在上一篇“一点儿不会”的系列随笔中说大概一周会发个2~3篇关于Unity的学习笔记.可这就两周过去了,我还停留在一篇的进度上,主要是这两周发生了一些事情导致我更新缓慢.其实截至目前为止,上 ...

  4. 删除元素 不存在 NO 存在 输出余下元素

    #include<stdio.h> #include<stdlib.h> #define N 5 #define NULL 0 #define OK 1 #define ERR ...

  5. class_create()

    #define class_create(owner, name)               \({                                              \   ...

  6. 内核MKDEV(MAJOR, MINOR)宏

    版本:linux-2.6.24.4宏:    MKDEV(MAJOR, MINOR);  说明: 获取设备在设备表中的位置.        MAJOR   主设备号        MINOR   次设 ...

  7. SQL 分组排序分页(大神帮写的膜拜一下)

    查询全部: SELECT P3.ID, P3.Name, P3.AddTimeFROM (SELECT Name, MAX(AddTime) AS MaxAddTime FROM Product AS ...

  8. Image.FrameDimensionsList 属性-----具体使用案例2

    图片的拆分 1.保存png图片 using System; using System.Collections.Generic;using System.ComponentModel;using Sys ...

  9. BZOJ 3143 游走(高斯消元)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3143 题意:一个无向连通图,顶点从1编号到n,边从1编号到m.小Z在该图上进行随机游走, ...

  10. Check if KeyValuePair exists with LINQ's FirstOrDefault

    http://stackoverflow.com/questions/793897/check-if-keyvaluepair-exists-with-linqs-firstordefault 问题: ...