zoukankan      html  css  js  c++  java
  • DllMain函数

    Windows在加载DLL的时候,需要一个入口函数,就如同控制台或DOS程序需要main函数、WIN32程序需要WinMain函数一样。在前面的例子中,DLL并没有提供DllMain函数,应用工程也能成功引用DLL,这是因为Windows在找不到DllMain的时候,系统会从其它运行库中引入一个不做任何操作的缺省DllMain函数版本,并不意味着DLL可以放弃DllMain函数。

      根据编写规范,Windows必须查找并执行DLL里的DllMain函数作为加载DLL的依据,它使得DLL得以保留在内存里。这个函数并不属于导出函数,而是DLL的内部函数。这意味着不能直接在应用工程中引用DllMain函数,DllMain是自动被调用的。

      我们来看一个DllMain函数的例子(单击此处下载本工程附件)。
     1 BOOL APIENTRY DllMain( HANDLE hModule, 
    2 DWORD ul_reason_for_call,
    3 LPVOID lpReserved
    4 )
    5 {
    6 switch (ul_reason_for_call)
    7 {
    8 case DLL_PROCESS_ATTACH:
    9 printf("\nprocess attach of dll");
    10 break;
    11 case DLL_THREAD_ATTACH:
    12 printf("\nthread attach of dll");
    13 break;
    14 case DLL_THREAD_DETACH:
    15 printf("\nthread detach of dll");
    16 break;
    17 case DLL_PROCESS_DETACH:
    18 printf("\nprocess detach of dll");
    19 break;
    20 }
    21 return TRUE;
    22 }


      DllMain函数在DLL被加载和卸载时被调用,在单个线程启动和终止时,DLLMain函数也被调用,ul_reason_for_call指明了被调用的原因。原因共有4种,即PROCESS_ATTACH、PROCESS_DETACH、THREAD_ATTACH和THREAD_DETACH,以switch语句列出。
    来仔细解读一下DllMain的函数头BOOL APIENTRY DllMain( HANDLE hModule, WORD ul_reason_for_call, LPVOID lpReserved )。

      APIENTRY被定义为__stdcall,它意味着这个函数以标准Pascal的方式进行调用,也就是WINAPI方式;

      进程中的每个DLL模块被全局唯一的32字节的HINSTANCE句柄标识,只有在特定的进程内部有效,句柄代表了DLL模块在进程虚拟空间中的起始地址。在Win32中,HINSTANCE和HMODULE的值是相同的,这两种类型可以替换使用,这就是函数参数hModule的来历。

      执行下列代码:
     1 hDll = LoadLibrary("..\\Debug\\dllTest.dll");
    2 if (hDll != NULL)
    3 {
    4 addFun = (lpAddFun)GetProcAddress(hDll, MAKEINTRESOURCE(1));
    5 //MAKEINTRESOURCE直接使用导出文件中的序号
    6 if (addFun != NULL)
    7 {
    8 int result = addFun(2, 3);
    9 printf("\ncall add in dll:%d", result);
    10 }
    11 FreeLibrary(hDll);
    12 }


      我们看到输出顺序为:

      process attach of dll

      call add in dll:5

      process detach of dll

      这一输出顺序验证了DllMain被调用的时机。

      代码中的GetProcAddress ( hDll, MAKEINTRESOURCE ( 1 ) )值得留意,它直接通过.def文件中为add函数指定的顺序号访问add函数,具体体现在MAKEINTRESOURCE ( 1 ),MAKEINTRESOURCE是一个通过序号获取函数名的宏,定义为(节选自winuser.h):
     1 #define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i)))
    2
    3 #define MAKEINTRESOURCEW(i) (LPWSTR)((DWORD)((WORD)(i)))
    4
    5 #ifdef UNICODE
    6
    7 #define MAKEINTRESOURCE MAKEINTRESOURCEW
    8
    9 #else
    10
    11 #define MAKEINTRESOURCE MAKEINTRESOURCEA

    转自http://www.cppblog.com/ivenher/articles/1315.html
  • 相关阅读:
    SQLServer如何批量替换某一列中的某个字符串
    能成为一名合格的Java架构师
    来看看Uber的司机支持服务签到及预约系统的架构设计思路
    什么是三层架构?你真的理解分层的意义吗?
    京东7Fresh新零售架构设计分析
    解密京东千亿商品系统核心架构
    因特尔黑科技:黑暗中快速成像系统
    分布式缓存架构设计
    各种排序算法汇总小结
    系统架构设计之-任务调度系统的设计
  • 原文地址:https://www.cnblogs.com/goodhacker/p/2299974.html
Copyright © 2011-2022 走看看