李sir_Blog

博客园 首页 联系 订阅 管理

如果想确认一个dll是否已经被映射到进程空间中,尽量使用GetModuleHandle,最好不要冒然使用LoadLibrary(Ex).

GetProcAddress可以传递函数名或者序号(通过MAKEINTRESOURCE(2)来"制作"序号).

四.DllMain(Dll入口)
其实,DllMain函数并不是最初的入口,它被_DllMainCRTStartup函数调用。
当系统调用_DllMainCRTStartup并传递DLL_PROCESS_ATTACH时,此函数初始化Dll中的所有全局变量以及静态成员变量等等,然后才调用DllMain并传递DLL_PROCESS_ATTACH;当系统传递DLL_PROCESS_DETACH时,此函数首先调用DllMain并传递DLL_PROCESS_DETACH,当DllMain返回后才调用全局或静态变量的析构函数。
如果不想在进程创建或销毁时收到DLL_THREAD_ATTACH或者DLL_THREAD_DETACH消息,那么可以在DLL_PROCESS_ATTACH时调用DisableThreadLibraryCalls,这将提高一些效率。

五.延迟加载Dll
说实话以前没有注意过这么一个好用的特性。看过本节后我知道了它。延迟加载用于隐式链接Dll的程序中。
要使一个dll延迟加载,就要在.exe上做手脚。需要修改工程属性,添加如下命令,则在链接时在输入节中将不包含该Dll的任何信息,从而导致.exe加载时不会加载该Dll.

     /Lib:DelayImp.lib
     
/DelayLoad:MyDll.dll 

这样,基本上就已经完成了对一个Dll延迟加载的处理。关于具体原理,书中是这样说的:

The /Lib switch tells the linker to embed a special function, _ _delayLoadHelper, into your executable. The second switch tells the linker the following things:
•Remove MyDll.dll from the executable module
's import section so that the operating system loader does not implicitly load the DLL when the process initializes.
•Embed a 
new Delay Import section (called .didata) in the executable indicating which functions are being imported from MyDll.dll.
•Resolve calls to the delay
-loaded functions by having calls jump to the _ _delayLoadHelper function.


如果短期内不想使用延迟加载的dll,那么可以暂时卸载它,需要的操作是添加一个链接开关:
/Delay:unload
然后在代码中,需要想要卸载Dll的地方调用  _ _FUnloadDelayLoadedDLL ,传递的名字必须与 /DelayLoad 开关所传递的名字完全相同(包括大小写)。不要使用FreeLibrary代替 _ _FUnloadDelayLoadedDLL 。如果不添加/Delay:unload开关而调用 _ _FUnloadDelayLoadedDLL ,那么这个函数会返回FALSE而不卸载任何dll.

六.函数转发器
函数转发器其实就是在Dll的导出函数里直接调用另一个Dll的函数。可以给自己创建的Dll的添加一些转发器,借花献佛。

// Function forwarders to functions in DllWork
#pragma comment(linker, "/export:SomeFunc=DllWork.SomeOtherFunc")


七.改变dll的基址
最好给自己创建的可能在同一工程中使用的不同Dll分别制定不同的Base Address,这样可以避免多个Dll同时要求映射到同一地址。虽然不会导致程序崩溃,但是系统要额外的重新定位剩余Dll中的地址。
方法是使用/base:"0x--------"链接命令。

posted on 2010-06-03 15:25  李sir  阅读(192)  评论(0)    收藏  举报