可以调用.exe的DllMain吗?

时间:2009-01-16 15:16:37

标签: winapi dll exe

我的问题与this one不完全相同(这不是理论上的,只有没有消息循环的主线程,InitInstance和ExitInstance都没有适合的调用)。

我正在使用没有消息循环的控制台应用程序;这个应用程序使用LoadLibrary函数加载一个exe,以便它可以使用其导出的函数。坏消息:没有调用exe的DllMain函数(我验证了符号表,使用def文件,DllMain正确显示); the doc says如果加载的模块是DLL(太糟糕),则调用它。

调用LoadLibrary时可能会导致exe的DllMain函数执行的条件(如果存在)有什么条件(可能再次调用FreeLibrary时)?

祝你好运

4 个答案:

答案 0 :(得分:4)

最明显的条件是调用LoadLibrary()的进程显式获取GetProcAddress(“DllMain”)然后调用它。

答案 1 :(得分:3)

条件是:

1)正在加载的二进制文件被编译为DLL(当使用gcc / ld时它表示使用--shared选项;如果使用--shared,则生成的文件将是一个dll,并且不会运行,请参阅下文)

2)IMAGE_FILE_DLL在正在加载的二进制文件的PE文件头中设置。如果已设置,则file为dll,并且Windows链接器在将此文件链接到您的程序时将为您调用其DllMain()函数(无论它如何链接 - LoadLibrary()在运行时或{ {1}}在编译时)。为此,文件也必须满足(1)。但是使用此标志,正在加载的二进制文件将无法运行。如果未设置-llibraryname,则在将文件加载到您的程序时,将不会调用IMAGE_FILE_DLL

使用DllMain()编译dll,然后从其标题中手动删除--shared(即使用十六进制编辑器)将无效 - 当您运行它时,只会执行IMAGE_FILE_DLL,并且DllMain()将是一个未定义的数字(我的机器上为fdwReason)。

<强>更新

Windows上的所有DLL和EXE文件都是PE文件,区别在于它们的链接方式以及标题中设置的标志。这就是为什么我写0x28ffd4,而不是file being loaded

最后一段还描述了将文件编译为dll,然后通过弄乱其标题将其转换为exe的方案。它不起作用。

命名与它无关(您可以选择任何名称,并且通过一些dll being loaded + pexports修补,您可以为.exe文件创建导入库,并能够将其链接为dlltool

澄清:

  • 如果你在没有-lexenamewithoutextension的情况下编译它:
    • --shared将不会在其中设置,它将是可运行的,但在链接时不会调用DllMain()。
  • 如果您使用IMAGE_FILE_DLL进行编译:
    • --shared将被设置在其中,它不会被运行,但是当你链接它时会调用DllMain()。
  • 如果你在没有IMAGE_FILE_DLL的情况下编译它,那么手动打开它中的--shared标志:
    • 它将不再可运行,并且在链接时不会调用DllMain()。
  • 如果使用IMAGE_FILE_DLL进行编译,请手动关闭其中的--shared标记:
    • 它将是可运行的,但是将执行DllMain()而不是main(),并且在链接时不会调用DllMain()。

答案 2 :(得分:1)

Windows确实完全忽略了该函数的名称“DllMain”(Windows NT 3.x的旧Windows API文档明确说明了这一点。)

加载DLL时不是函数DllMain(),而是调用位于文件入口点的函数。

当然,链接器将以DllMain()为此函数的方式创建DLL文件。

但是对于EXE文件,入口函数(将调用WinMain())位于入口点。

因此很明显,当将EXE文件作为DLL加载时,Windows无法调用此函数。

答案 3 :(得分:0)

完成MSalters的好答案:

然后,在LoadLibrary之后使用DLL_XXX_ATTACH调用“假”DllMain,并在FreeLibrary之前调用DLL_XXX_DETACH,并手动调用其他调用。

下面的另一个实现是构建和加载一个接口DLL,它可以自动回调它的假DllMain上的EXE(我不知道它是否可行);但它可能比在许多情况下手动调用伪DllMain更复杂。(不能在DllMain中加载LoadLibrary)