如何在64位窗口中加载32位DLL

时间:2017-02-21 06:40:51

标签: c++ dll x86-64

我在64位窗口中安装了Mozilla FireFox x64,现在我想要LoadLibrary(mozglue.dll),但我收到错误编号193

LoadLibrary(mozglue.dll)适用于Mozilla FireFox 86

的32位窗口

我使用此代码:

#include <Windows.h>
#include <strsafe.h>

int main()
{
    HMODULE hndl;
    DWORD dwError = 0;
    WCHAR errorBuff[MAX_PATH] = {};

    hndl = LoadLibraryW(L"C:\\Program Files\\Mozilla Firefox\\mozglue.dll");
    dwError = GetLastError();
    StringCbPrintfW(errorBuff, MAX_PATH, L"%d", dwError);
    MessageBoxW(NULL, errorBuff, L"GetLastError", MB_OK);
    FreeLibrary(hndl);

    return 0;
}

此代码有什么问题?

修改

我用:

LoadLibraryExW(L"C:\\Program Files\\Mozilla Firefox\\mozglue.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);

而不是:

LoadLibraryW(L"C:\\Program Files\\Mozilla Firefox\\mozglue.dll");

现在GetLastError返回0但GetProcAddress失败......

    #include <Windows.h>
    #include <strsafe.h>


    typedef enum SECItemType {
        siBuffer = 0,
        siClearDataBuffer = 1,
        siCipherDataBuffer,
        siDERCertBuffer,
        siEncodedCertBuffer,
        siDERNameBuffer,
        siEncodedNameBuffer,
        siAsciiNameString,
        siAsciiString,
        siDEROID,
        siUnsignedInteger,
        siUTCTime,
        siGeneralizedTime
    };

    struct SECItem {
        SECItemType type;
        unsigned char *data;
        size_t len;
    };

    typedef enum SECStatus {
        SECWouldBlock = -2,
        SECFailure = -1,
        SECSuccess = 0
    };


    typedef struct PK11SlotInfoStr PK11SlotInfo;
    typedef SECStatus(*NSS_Init) (const char *);
    typedef SECStatus(*NSS_Shutdown) (void);
    typedef PK11SlotInfo * (*PK11_GetInternalKeySlot) (void);
    typedef void(*PK11_FreeSlot) (PK11SlotInfo *);
    typedef SECStatus(*PK11_Authenticate) (PK11SlotInfo *, int, void *);
    typedef SECStatus(*PK11SDR_Decrypt) (SECItem *, SECItem *, void *);

    PK11_GetInternalKeySlot PK11GetInternalKeySlot;
    PK11_FreeSlot PK11FreeSlot;
    PK11_Authenticate PK11Authenticate;
    PK11SDR_Decrypt PK11SDRDecrypt;
    NSS_Init fpNSS_INIT;
    NSS_Shutdown fpNSS_Shutdown;



    BOOL loadFunc()
    {
        HMODULE hndl;
        DWORD dwError = 0;
        WCHAR errorBuff[MAX_PATH] = {};
        BOOL retVal = FALSE;

        hndl = LoadLibraryExW(L"C:\\Program Files\\Mozilla Firefox\\mozglue.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
        dwError = GetLastError();
        StringCbPrintfW(errorBuff, MAX_PATH, L"%d", dwError);
        MessageBoxW(NULL, errorBuff, L"GetLastError", MB_OK);


        hndl = LoadLibraryExW(L"C:\\Program Files\\Mozilla Firefox\\nss3.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
        dwError = GetLastError();
        StringCbPrintfW(errorBuff, MAX_PATH, L"%d", dwError);
        MessageBoxW(NULL, errorBuff, L"GetLastError", MB_OK);

        if (hndl)
        {
            fpNSS_INIT = (NSS_Init)GetProcAddress(hndl, "NSS_Init");
            fpNSS_Shutdown = (NSS_Shutdown)GetProcAddress(hndl, "NSS_Shutdown");
            PK11GetInternalKeySlot = (PK11_GetInternalKeySlot)GetProcAddress(hndl, "PK11_GetInternalKeySlot");
            PK11FreeSlot = (PK11_FreeSlot)GetProcAddress(hndl, "PK11_FreeSlot");
            PK11Authenticate = (PK11_Authenticate)GetProcAddress(hndl, "PK11_Authenticate");
            PK11SDRDecrypt = (PK11SDR_Decrypt)GetProcAddress(hndl, "PK11SDR_Decrypt");
        }
        return !(!fpNSS_INIT || !fpNSS_Shutdown || !PK11GetInternalKeySlot || !PK11Authenticate || !PK11SDRDecrypt || !PK11FreeSlot);
    }



    int main()
    {
        if (loadFunc())
        {
            MessageBoxW(NULL, L"OK", L"", MB_OK);
        }
        else
        {
            MessageBoxW(NULL, L"NO", L"", MB_OK);
        }

        return 0;
    }

2 个答案:

答案 0 :(得分:1)

您的第一个问题是64位程序无法加载32位DLL,而32位程序无法加载64位DLL以执行代码。 MSDN的Process Interopability信息中描述了这一点:

  

您可以使用仿真层在64位Windows上运行基于Win32的应用程序。有关更多信息,请参阅运行32位应用程序。

     

在64位Windows上,64位进程无法加载32位动态链接库(DLL)。此外,32位进程无法加载64位DLL。

如果您需要同时支持32位程序和64位,最简单的方法是安装32位版本的Mozilla DLL(通过32位Mozilla安装),并为64位执行相同的操作Mozilla的。默认情况下,64位Mozilla应放在C:\Program Files\Mozilla Firefox\C:\Program Files (x86)\Mozilla Firefox\中的32位Mozilla中。在加载像mozglue.dll

这样的DLL时,在构建64位应用程序与32位应用程序时,您需要考虑不同的目录

您不会检查hndl是否为NULL。您应该只检查GetLastError返回的句柄是否为NULL,而不是当它不是NULL时。其次,使用LoadLibraryExW调用LOAD_LIBRARY_AS_DATAFILE可以加载DLL资源,但不允许您使用GetProcAddress检索函数地址。这在LoadLibraryEx的MSDN文档中有记录:

  

LOAD_LIBRARY_AS_DATAFILE 0x00000002

     

如果使用此值,系统会将文件映射到调用进程的虚拟地址空间,就好像它是一个数据文件一样。执行或准备执行映射文件没有任何操作。因此,您无法使用此DLL调用 GetModuleFileName,GetModuleHandle或 GetProcAddress 等函数。使用此值会导致写入只读内存以引发访问冲突。如果要仅加载DLL以从中提取消息或资源,请使用此标志。

记住上面的想法我用修改后的loadfunc编译了你的代码并将其构建为64位应用程序。完成后,程序在MessageBox中打印OK

BOOL loadFunc()
{
    HMODULE hndl;
    DWORD dwError = 0;
    WCHAR errorBuff[MAX_PATH] = {};
    BOOL retVal = FALSE;

    hndl = LoadLibraryW(L"C:\\Program Files\\Mozilla Firefox\\mozglue.dll");
    // if the handle is NULL then check for an error otherwise proceed
    if (!hndl)
    {
        dwError = GetLastError();
        StringCbPrintfW(errorBuff, MAX_PATH, L"%d", dwError);
        MessageBoxW(NULL, errorBuff, L"GetLastError", MB_OK);
        return TRUE;
    }

    hndl = LoadLibraryW(L"C:\\Program Files\\Mozilla Firefox\\nss3.dll");
    // if the handle is NOT NULL then try to retrieve the method addresses
    if (hndl)
    {
        fpNSS_INIT = (NSS_Init)GetProcAddress(hndl, "NSS_Init");
        fpNSS_Shutdown = (NSS_Shutdown)GetProcAddress(hndl, "NSS_Shutdown");
        PK11GetInternalKeySlot = (PK11_GetInternalKeySlot)GetProcAddress(hndl, "PK11_GetInternalKeySlot");
        PK11FreeSlot = (PK11_FreeSlot)GetProcAddress(hndl, "PK11_FreeSlot");
        PK11Authenticate = (PK11_Authenticate)GetProcAddress(hndl, "PK11_Authenticate");
        PK11SDRDecrypt = (PK11SDR_Decrypt)GetProcAddress(hndl, "PK11SDR_Decrypt");
    }
    // the handle was NULL if we get here so show the error
    else
    {
        dwError = GetLastError();
        StringCbPrintfW(errorBuff, MAX_PATH, L"%d", dwError);
        MessageBoxW(NULL, errorBuff, L"GetLastError", MB_OK);
        return TRUE;
    }
    return !(!fpNSS_INIT || !fpNSS_Shutdown || !PK11GetInternalKeySlot || !PK11Authenticate || !PK11SDRDecrypt || !PK11FreeSlot);
}

对于32位程序,您需要将上面代码中的路径更改为前面提到的32位Mozilla目录,并编译为x86 32位应用程序。前面提到的32位代码的默认路径是C:\Program Files (x86)\Mozilla Firefox\

我从download link下载了64位版本的Mozilla,并从this link下载了32位Mozilla安装。

答案 1 :(得分:0)

您要么尝试将32位DLL加载到64位进程,要么将64位DLL加载到32位进程中。它无法完成。

我想如果你的'Mozilla FireFox x64'mozglue.dll是64位的 - 那么你需要编译并将你的测试程序链接为64位。