|
d DynamicDumpModule(HMODULE hModule)函数相对应的函数相同。
动态调用某DLL导出函数的例子:
PFN_DUMPMODULE pfnDumpModule=(PFN_DUMPMODULE)GetProcAddress(hDll,"DumpModule");
If(pfnDumpModule!=NULL)
{
pfnDumpModule(hDll);
}
;/span>
DLL的入口点函数
一个DLL可以有一个入口点函数,系统会在不同的时候调用这个函数。这些调用是通知性质的,通常被DLL用来执行与进程或线程有关的初始化和清理工作。
如果不需要执行这些操作,可以不必再源代码中不实现此函数。
如果需要DLL接受这些通知,就应该按照如下的格式来实现该函数。
Bool WINAPI DllMain(HINSTANCE hInsDll,DWORD fdwReason,PVOID fImpLoad)
{
Swith(fdwReason)
{
Case DLL_PROCESS_ATTACH:
//DLL被映射到进程地址空间是,执行此处代码。
Break;
Case DLL_THREAD_ATTACH:
//线程被创建的时候执行。
Break;
Case DLL_THREAD_DETACH:
//线程终止运行时执行。
Break;
Case DLL_PROCESS_DETACH:
//DLL被卸载的时候执行。
Break;
}
}
hInstDll是该DLL实例的句柄。它是DLL文件被映射到进程地址空间的虚拟地址。通常将这个参数保存在全局变量中。这样在DLL的其他导出函数中就可以使用。
如果DLL是被隐式载入的,fImpLoad为非零值,显式的话fImportLoad为0。
fdwReason表示系统调用入口点函数的原因。它是switch语句的参数。可以是上述四个值。分别表示四种情况。后续将会详细介绍每一种情况。
注意:DLL使用DllMain对自己进行初始化。DllMain执行的时候,其他DLL的可能还未被初始化。这意味着我们应该避免在DllMain中调用从其他DLL中导出的函数。
DLL_PROCESS_ATTACH通知 www.2cto.com
当系统第一次将一个DLL映射到进程地址空间是,会调用DllMain函数,并给fdwReason传入DLL_PROCESS_ATTACH。注意:只有在该DLL是第一次被调用到进程地址空间中时,才会调用DllMain。如果以后再次调用LoadLibrary(Ex)时,OS仅仅是递增该DLL在此进程的使用计数,并不会再次调用DllMain。
当DLL在处理DLL_PROCESS_ATTACH时,应该根据需要执行与进程相关的初始化。如DLL中包含一些函数,需要使用自己的堆,可以在进程加载时执行一些堆的初始化工作。
处理DLL_PROCESS_ATTACH时,DllMain的返回值表示DLL的初始化是否成功。如初始化成功,应返回TRUE,否则应返回false。
下面来看看DllMain调用的时机:
创建新进程时,系统为该进程分配地址空间,并将exe可执行文件和所需要的DLL映射到进程地址空间。然后创建主线程,并用主线程来调用每个DLL的DllMain函数,同时传入DLL_PROCESS_ATTACH。当所有已映射的DLL完成对该通知的处理后,系统会让主进程执行可执行模块的C/C++运行库的启动代码。然后执行可执行模块的入口点函数(_tmain或_tWinMain)。如果任意一个DLL的DllMain返回false,就说明初始化失败,系统会将所有文件映像从地址空间中清除,向用户显示错误信息。
显式载入DLL的过程:
进程调用LoadLibrary(Ex),该函数对DLL进行定位,并将该DLL映射到进程地址空间。然后会让调用LoadLibrary(Ex)的线程调用DllMain函数,并传入DLL_PROCESS_ATTACH。当DLL的DllMain函数完成了对通知的处理后,系统会让LoadLibrary返回。这样线程就可以继续执行。
注意:DllMain是在进程调用LoadLibrary(Ex)的时候调用的。它返回到LoadLibrary(Ex)函数内。
未完待续。。。。。
《参考自windows核心编程》第五版第四部分。以上仅仅是个人总结,如有纰漏请不吝赐教!
|