C20、高级DLL
来源:互联网 发布:软件需求分析面试 编辑:程序博客网 时间:2024/06/05 04:52
一、显式加载DLL模块:
a) HINSTANCE LoadLibrary(PCTSTR pszDllPathName);
b) HINSTANCE LoadLibraryEx(
PCTSTR pszDllPathName, //路径(包含文件全名)。
HANDLE hFile; // NULL
DWORD dwFlags); // 0
dwFlags可以使用的其他标志:
u DON’T_RESOLVE_DLL_REFERENCES:使系统不必调用DllMain函数;如果此DLL需要其他DLL,系统不自动加载。
u LOAD_LIBRARY_AS_DATAFILE:系统不准备执行文件中的代码(就像是数据文件一样)。如果DLL中只包含资源(不包含函数)或加载.exe文件而不启动新线程(可以访问其中的资源)需要设定此标志。
u LOAD_WITH_ALTERED_SEARCH_PATH:用于改变搜索DLL的算法(常规是按C19中的顺序搜索),首先搜索pszDllPathName设定的目录。
二、显式御载DLL模块:
a) BOOL FreeLibrary(HINSTANCE hinstDll);
b) VOID FreeLibraryAndExitThread(HINSTANCE hinstDll, DWORD dwExitCode); //如果对同一个DLL多次调用LoadLibrary(Ex),需要用此函数。
注:DLL加载时,系统启动一个线程。
u 测试DLL是否已经被映射到进程的地址空间:
HINSTANCE GetModuleHandle(PCTSTR pszModuleName);
u 查询DLL的全路径名:
DWORD GetModuleFileName(hinstModule,
pszPathName, // 缓存地址,TCHAR pszPathName[MAX_PATH]
DWORD cch);// 缓存的大小
三、显式链接到一个输出符号:
FARPROC GetProcAddress(
HINSTANCE hinstDll,
PCSTR pszSymbolName);// 可以使用符号名或序号:MAKEINTRESOURCE(2)
四、进入点函数(初始化使用):
BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad);
应该避免:
u 调用LoadLibrary(Ex), FreeLibrary
u 从其他DLL中输入的函数(User, Shell, ODBC, COM, RPC, 套接字函数)。
u 因为全局或静态C++对象也在调用DllMain时初始化,同样也应避免上述问题。
五、延迟加载DLL:
使用目的:如果在WIN2000中设计的程序使用了WIN98没有的新函数,而要在98上运行,如果不应有延迟加载技术,将会终止进程。方法(两步):
1. 常规建立DLL和可执行模块
2. 链接可执行模块时,添加延迟加载开关:
a) /Lib: DelayImp.lib // 需要DelayImp.lib库(
b) /DelayLoad: MyDll.dll
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 实践:把下面的代码添加给需要此功能的模块
u #include <delayimp.h> // 需要的头文件
u #pragma comment(lib, "Delayimp.lib") // 库
u #pragma comment(linker, "/DelayLoad:DelayLoadLib.dll") // 延迟加载的库
u #pragma comment(linker, "/Delay:unload") // 可以手工卸载,可选
u //#pragma comment(linker, "/Delay:nobind") // 不绑定,通常不要!
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
其他方面:
3. 卸载DLL时(如果不自己卸载,则不要这项修改!):
a) 开关:/delay:unload // 如果不用此开关,下面的函数将不执行操作!
b) 卸载DLL(不能使用FreeLibrary,否则函数地址不会被清除),使用:
BOOL __FUnloadDelayLoadedDLL(PCSTR szDll);//不包含路径
4. 延迟加载使.exe文件变大。阻止变大,使用开关:/Delay:nobind(不建议用)。
5. 挂钩函数。接收__delayLoadHelper的进度通知和错误通知,用法(两步):
a) 自己编写挂钩函数(如DliHook);
b) DelayImp.lib库中俩个PfnDliHook类型的变量:__pfnDliNotifyHook, __pfnDliFailureHook。将两个中的一个设置为挂钩函数的地址(PfnDliHook __pfnDliNotifyHook = DliHook)
6. 细节:
u 程序运行时,对DLL中函数的调用,实际上是对DelayImp.lib库中的__delayLoadHelper函数的调用。__delayLoadHelper引用DLL的Delay Import节(调用LoadLibrary,GetProcAddres)调用函数。
u 如果有多个DLL需要延迟加载,则要为每一个DLL设定开关。
7. 异常处理:
u 如果加载失败,产生一个软件异常(ERROR_MOD_NOT_FOUND, ERROR_PROC_NOT_FOUND),(如果不用SHE处理,进程终止!),其信息包含在DelayLoadInfo结构中,szDll为DLL名字,dlp为函数(DelayLoadProc结构),dwLastError—什么原因引发的错误;如果是成功加载,hmodCur是DLL加载到的内存地址,pfnCur为函数地址。
六、函数转发(在DLL输出节中):
#pragma comment(linker, “/export:SomeFunc=DllWork.SomeOtherFunc”)
你在DLL输出的SomeFunc实际上位于DllWork.dll中的SomeOtherFunc。
七、已知的DLL:操作系统提供的某些DLL可以在注册表(KnownDLLs)中找到的DLL(称为已知的DLL)。
u 如果使用LoadLibrary(“someLib.dll”);(使用了.dll扩展名),系统首先查找注册表。如果找到someLib值,而且如果注册表指示的DLL是在someOtherLib.dll,系统则在系统目录(%SystemRoot%/System32)查找someOtherLib.dll,如果找到了,系统直接加载someOtherLib.dll而不加载someLib.dll;如果找不到,LoadLibrary(Ex)返回NULL(ERRO_FILE_NOT_FOUND)。
u 我们是否也可以把自己的DLL注册、放入系统目录?加载更快?
八、DLL转移(Windows98不支持):用于强制加载程序总是首先查找应用程序的目录。仅需在应用程序的目录中添加一个空文件,文件名必须是SuperApp.local。如:可执行文件名为myPrg.exe,添加一个(转移文件)myPrg.exe.local。
九、改变模块的位置(如果你的程序带有多个DLL模块)
每个可执行模块和DLL模块都有一个首选基地址(分别是:0x00400000,0x10000000),用于标识模块映射到进程的理想地址空间。如果不能加载到首选基地址,将产生移位节。
a) 可以创建不包含移位节的模块。
u 链接开关:/FIXED。可使模块变小,但不能被改变位置,如果不能加载到首选基地址,那么他就根本不能加载,“进程异常终止”!适用于仅包含资源的DLL。
u 链接开关:/SUBSYSTEM:WINDOWS,5.0或/SUBSYSTEM:CONSOLE,5.0。
b) 如果有多个模块加载到单个地址空间,必须为每个模块设置不同的首选基地址。“工程设置”->“Link”->“Output”->Base Address=设置的首选基地址(分配粒度64K)。
c) 如果你的程序带有多个DLL模块,有必要改变首选基地址。建议使用实用程序:Rebase.exe(,详见MSDN)。(可以在链接前后执行)。
示例:rebase –b 0x61000000 myDll.dll。
u 可以在改变前后,查看基地址:dumpbin /headers myDll.dll。在“OPTIONAL HEADER VALUES”的“image base”项。
十、绑定模块:(实用程序Bind.exe,查看MSDN)。使程序更快的初始化。在应用程序安装时执行。
示例:bind –u myPrg.exe;
u 可以在绑定前后分别查看其输入节:dumpbin /imports myPrg.exe。如果在结尾(Summary)前有“Bound to KERNEL32.dll [……] ……”,标识绑定成功!([ ] 内的内容为“时间戳”,其后面接“可读时间戳”)。
u 要把你的DLL模块(系统模块不必要)拷贝到与.exe同一个文件夹!
- C20、高级DLL
- DLL高级技巧
- DLL高级技术
- DLL高级技术2
- Dll高级功能
- DLL高级技术
- AIX hang 0c20 IN GPFS system
- windows核心编程--DLL高级
- windows核心编程--DLL高级
- Windows核心编程:DLL高级技术
- DLL高级技术之延迟载入
- windows核心编程---DLL高级技术Ex
- <PY><core python programming笔记>C20 Web编程
- linux系统编程手册阅读笔记-c20:信号的基本概念
- <c语言经典100例>c20 比赛顺序
- 从aspx文件到DLL文件之高级应用
- CPP高级编程总结---非MFC的DLL
- CPP高级编程总结之非MFC的DLL
- ...
- UTF—8和GBK的区别
- 用Visual C++干干净净地清除进程
- PERL SOCKET编程
- 监控线程设计
- C20、高级DLL
- Windows Vista各版本功能区别
- 意义按啊
- JAVA 数据挖掘工具
- 我的emacs的配置文件。
- C21、线程本地存储(TLS)
- 在SLES 9下查看线程的cpu利用率
- 请多多关照
- ODBC编程