【问题标题】:How to load a 32bit DLL in a 64bit windows如何在 64 位窗口中加载 32 位 DLL
【发布时间】:2017-07-10 15:58:00
【问题描述】:

我在 64 位 Windows 中安装了 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;
    }

【问题讨论】:

  • 你是如何编译你的代码的?你是编译成64位的吗?您在此处安装的 mozglue 很可能是 64 位,与 Firefox 的其余部分一样,如果您的可执行文件是 32 位,则无法加载它。
  • 您可以在 64 位 Windows 上将 32 位 DLL 加载到 32 位 进程 中,但不能将其加载到 64位过程。所以你必须安装 32 位 Firefox。
  • 我为 32 位编译一次,为 64 位编译一次,但都得到错误 193
  • 安装 64 位 Firefox 时需要这样做
  • 如果您完成了错误 193 并遇到了另一个问题,请接受最有帮助的答案并提出另一个问题。

标签: c++ winapi dll x86-64


【解决方案1】:

您要么尝试将 32 位 DLL 加载到 64 位进程中,要么将 64 位 DLL 加载到 32 位进程中。做不到。

我想如果你有“Mozilla FireFox x64”,mozglue.dll 是 64 位的 - 所以你需要将你的测试程序编译和链接为 64 位。

【讨论】:

  • 我知道,但是我安装了x64 Firefox,我尝试加载的mozglue是安装后创建的dll...
  • 那么,dumpbin/dependency walker 说你的测试 exe 是什么(32 位还是 64 位?)它说 mozglue 是什么?
  • LOAD_LIBRARY_AS_DATAFILE 说“这个 DLL 不包含代码”。显然 GetProcAddress 不起作用 - 您已经告诉操作系统 DLL 不包含任何过程。你还没有回答我关于 exe 和 dl 的问题..
【解决方案2】:

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

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

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

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


您不检查hndl 是否为NULL。如果返回的句柄为 NULL,则只需要检查 GetLastError,而不是当它不为 NULL 时。其次,使用LOAD_LIBRARY_AS_DATAFILE 调用LoadLibraryExW 允许您加载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 下载了 Mozilla 的 64 位版本,从 this link 下载了 32 位 Mozilla 安装。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-06
    • 1970-01-01
    • 2014-08-10
    • 2013-03-02
    • 2011-08-12
    • 2018-05-29
    • 2011-01-16
    • 1970-01-01
    相关资源
    最近更新 更多