MFC应用程序和共享库

时间:2015-10-05 07:30:46

标签: c++ visual-c++ dll mfc

我有一个看似用MFC编写的应用程序(进程黑客和DependencyWalker显示链接到MFC90)。

此外,安装路径中还有一个库(FTD2XX)。但是DependencyWalker不会显示lib的MFC90链接并显示:

SetupAPI.dll
KERNEL32.dll
USER32.dll
ADVAPI32.dll

lib构建在什么框架中? 我没有MFC的经验。我的编译器中没有信息,VC ++库是否可用于链接MFC应用程序。

1 个答案:

答案 0 :(得分:1)

如果要将调用记录到dll,最好的方法是编写代理dll(dll重定向)。但对于 ,您必须知道要覆盖的函数的签名(语法) ,即参数的确切数量,类型和返回类型等。如果我可以假设您以某种方式可以找到ftd2xx.dll中所有函数的签名,那么完成它只是简单。

获取dll函数和序号: 为此,只需使用带有Visual Studio的dumpbin.exe(通过运行Visual Studio命令提示符使用它)

  

dumpbin.exe / exports {yourpath} \ ftd2xx.dll> ftd2xx.txt

现在你的ftd2xx.txt包含ftd2xx.dll的所有函数名和序号。您甚至可以使用依赖性walker导出并获取此列表。

创建自己的名为ftd2xx.dll的dll: 打开Visual Studio,选择VC ++>> Win32>> Win32项目>> Dll(带有导出符号选项),最后使用#pragma指令在你的dll代码中声明所有导出的原始dll函数,如下所示,

//#pragma comment (linker, "/export:<function>=<origdll_name>.<function>,@<ordinal_number>")

#pragma comment (linker, "/export:FT_Open=ftd2xx_.FT_Open,@1")
#pragma comment (linker, "/export:FT_Close=ftd2xx_.FT_Close,@2")
// :
// :
// :
// delcare all your exported functions here with ordinal number
// :
// :
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
}

现在,您需要编写自己的函数,它可以伪装成ftd2xx.dll的原始函数,当应用程序调用ftd2xx.dll的原始函数时将调用该函数。以下代码只是为了解释它是如何工作的。正如我之前所说,您需要知道要覆盖的dll函数的确切签名(重定向)。并且还要记住,您需要在想要做的任何事情之后调用原始函数,否则您的应用程序可能会出现意外行为。

假设FT_Close()函数没有参数并且返回void,我只是举例说明我用代理NewFT_Close()函数覆盖ftd2xx.dll的FT_Close()函数。请注意,如果您覆盖某个函数,则将其从#pragma指令中删除并将其添加到.def文件中(将新的ftd2xx.def文件添加到您的项目中并声明您的新函数,如下所示)。

DEF文件示例

LIBRARY ftd2xx.dll
EXPORTS
FT_Close = NewFT_Close @2

Dll代码示例

HINSTANCE   hInstance = NULL;        // handle to ftd2xx.dll
FARPROC     fpFTClose = {NULL};      // function pointer to hold original function address

extern "C" void __stdcall NewFT_Close()
{
    // This is our proxy function for FT_Close()
    // Do whatever you want to do here and the 
    // finally call the original FT_Close() using 
    // the function pointer we got from GetProcAddress()
    typedef void (__stdcall *PFTCLOSE)();
    PFTCLOSE pFc = (PFTCLOSE)fpFTClose;
    if(pFc) pFc();
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            // Load the original dll in to the memory and get the handle
            hInstance = LoadLibraryA("ftd2xx_.dll");
            if(!hInstance) return FALSE;
            // Get the address of the function to be overriden
            fpFTClose = GetProcAddress(hInstance,"FT_Close");
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            // Our dll is getting unloaded from the application, unload original as well
            FreeLibrary(hInstance);
            break;
    }
    return TRUE;
}

请注意,原始dll在LoadLibraryA()调用中称为ftd2xx_.dll。因此,将原始dll重命名为ftd2xx_.dll或将其命名为您想要的任何名称。构建您的代理DLL代码并将您的代理DLL(ftd2xx.dll)带到原始ftd2xx.dll存在的路径。现在,您的应用程序将像往常一样调用ftd2xx.dll(代理),但ftd2xx.dll将在内部调用原始的dll ftd2xx_.dll。

更新#1: 我一直提到你需要知道你试图覆盖的函数的签名,幸运的是我刚刚在linux版本的驱动程序中找到了ftd2xx.h文件。

Linux version of ftd2xx

从上面的链接下载libftd2xx-i386-1.3.6.tgz文件并将其解压缩到一个文件夹(我使用7zip),进一步解压缩.tar文件以获取release文件夹,你会找到ftd2xx.h文件在“发布”文件夹中。你去,现在你有完整的功能签名的DLL,你知道如何编写代理DLL。祝你好运。