Chrome 的 NPAPI 插件无法通过 NP_Initialize

发布于 2024-12-11 09:03:49 字数 5021 浏览 0 评论 0原文

我一直在尝试编写一个使用 NPAPI 插件的 Chrome 扩展。我正在使用 mingw 来编译它。我最初很难让 Chrome 加载该插件,但现在我遇到了不同的问题。

我已经设法让 Chrome 调用 NP_GetEntryPoints 和 NP_Initialize,但之后它就崩溃了。这是到目前为止我的代码...

ma​​in.cpp

#include <iostream>
#include <cstdlib>
#include <Windows.h>
#include <npapi.h>
#include <npfunctions.h>
#define Exported extern "C" __declspec(dllexport)

NPNetscapeFuncs NPNFuncs;

Exported NPError NP_Initialize(NPNetscapeFuncs* pFuncs) {

    if (pFuncs == NULL)
        return NPERR_INVALID_FUNCTABLE_ERROR;

    if (HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
        return NPERR_INCOMPATIBLE_VERSION_ERROR;

    if (pFuncs->size < sizeof(NPNetscapeFuncs))
        return NPERR_INVALID_FUNCTABLE_ERROR;

    // Save functions
    NPNFuncs.size             = pFuncs->size;
    NPNFuncs.version          = pFuncs->version;
    NPNFuncs.geturlnotify     = pFuncs->geturlnotify;
    NPNFuncs.geturl           = pFuncs->geturl;
    NPNFuncs.posturlnotify    = pFuncs->posturlnotify;
    NPNFuncs.posturl          = pFuncs->posturl;
    NPNFuncs.requestread      = pFuncs->requestread;
    NPNFuncs.newstream        = pFuncs->newstream;
    NPNFuncs.write            = pFuncs->write;
    NPNFuncs.destroystream    = pFuncs->destroystream;
    NPNFuncs.status           = pFuncs->status;
    NPNFuncs.uagent           = pFuncs->uagent;
    NPNFuncs.memalloc         = pFuncs->memalloc;
    NPNFuncs.memfree          = pFuncs->memfree;
    NPNFuncs.memflush         = pFuncs->memflush;
    NPNFuncs.reloadplugins    = pFuncs->reloadplugins;
    NPNFuncs.getJavaEnv       = pFuncs->getJavaEnv;
    NPNFuncs.getJavaPeer      = pFuncs->getJavaPeer;
    NPNFuncs.getvalue         = pFuncs->getvalue;
    NPNFuncs.setvalue         = pFuncs->setvalue;
    NPNFuncs.invalidaterect   = pFuncs->invalidaterect;
    NPNFuncs.invalidateregion = pFuncs->invalidateregion;
    NPNFuncs.forceredraw      = pFuncs->forceredraw;*/

    // Success
    MessageBoxA(0, "NP_Initialize", "Log", 0);
    return NPERR_NO_ERROR;

}

Exported void NP_Shutdown() {

    MessageBoxA(0, "NP_Shutdown", "Log", 0);

}

    /* Entry points */
    NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* savedData) {

        MessageBoxA(0, "NPP_New", "Log", 0);
        return NPERR_NO_ERROR;

    }

    NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {

        MessageBoxA(0, "NPP_GetValue", "Log", 0);
        return NPERR_NO_ERROR;

    }

    /*** Omitted... All the other functions are here, with just a MessageBox call in them ***/

Exported NPError NP_GetEntryPoints(NPPluginFuncs* pFuncs) {

    if (pFuncs == NULL)
        return NPERR_INVALID_FUNCTABLE_ERROR;

    if (pFuncs->size < sizeof(NPPluginFuncs))
        return NPERR_INVALID_FUNCTABLE_ERROR;

    pFuncs->size                = sizeof(NPPluginFuncs);
    pFuncs->version             = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
    pFuncs->newp                = &NPP_New;
    pFuncs->destroy             = &NPP_Destroy;
    pFuncs->setwindow           = &NPP_SetWindow;
    pFuncs->newstream           = &NPP_NewStream;
    pFuncs->destroystream       = &NPP_DestroyStream;
    pFuncs->asfile              = &NPP_StreamAsFile;
    pFuncs->writeready          = &NPP_WriteReady;
    pFuncs->write               = &NPP_Write;
    pFuncs->print               = &NPP_Print;
    pFuncs->event               = &NPP_HandleEvent;
    pFuncs->urlnotify           = &NPP_URLNotify;
    pFuncs->getvalue            = &NPP_GetValue;
    pFuncs->setvalue            = &NPP_SetValue;
    pFuncs->javaClass           = NULL;
    pFuncs->gotfocus            = &NPP_GotFocus;
    pFuncs->lostfocus           = &NPP_LostFocus;
    pFuncs->urlredirectnotify   = &NPP_URLRedirectNotify;
    pFuncs->clearsitedata       = &NPP_ClearSiteData;
    pFuncs->getsiteswithdata    = &NPP_GetSitesWithData;

    MessageBoxA(0, "NP_GetEntryPoints", "Log", 0);
    return NPERR_NO_ERROR;

}

我向每个函数添加了 MessageBox 调用,因此我可以查看是否正在调用正确的函数。当我运行测试页(这是一个带有 标记的空白页)时,我收到一条消息说 NP_GetEntryPoints,然后又收到一条消息说 NP_Initialize,然后 Chrome 会弹出一个栏,提示我的插件已崩溃。我认为问题出在我的 NP_GetEntryPoints 中,但我就是看不到它......我做错了什么或忘记做什么吗?

我使用 : 进行编译

g++.exe -DWIN32 -D_WIN32 -D_WINDOWS -D_WIN32_WINNT=0x0600 -D_WIN32_IE=0x0600 -D_UNICODE -DUNICODE -static-libgcc -static-libstdc++ -c "main.cpp" -o main.o

windres.exe "resource.rc" "resource.o"

并使用以下命令链接到 .DLL:

g++.exe -Wl,--subsystem,windows -o "npplugin.dll" -s -shared main.o resource.o -lcomctl32 -lws2_32 -luxtheme -lgdi32 -lshell32 -lshlwapi

I've been trying to write an extension for Chrome that uses an NPAPI plugin. I'm using mingw to compile it. I struggled originally to get Chrome to load the plugin, but now I have a different problem.

I've managed to get Chrome to call NP_GetEntryPoints and NP_Initialize, but it crashes right after that. Here's my code so far...

main.cpp :

#include <iostream>
#include <cstdlib>
#include <Windows.h>
#include <npapi.h>
#include <npfunctions.h>
#define Exported extern "C" __declspec(dllexport)

NPNetscapeFuncs NPNFuncs;

Exported NPError NP_Initialize(NPNetscapeFuncs* pFuncs) {

    if (pFuncs == NULL)
        return NPERR_INVALID_FUNCTABLE_ERROR;

    if (HIBYTE(pFuncs->version) > NP_VERSION_MAJOR)
        return NPERR_INCOMPATIBLE_VERSION_ERROR;

    if (pFuncs->size < sizeof(NPNetscapeFuncs))
        return NPERR_INVALID_FUNCTABLE_ERROR;

    // Save functions
    NPNFuncs.size             = pFuncs->size;
    NPNFuncs.version          = pFuncs->version;
    NPNFuncs.geturlnotify     = pFuncs->geturlnotify;
    NPNFuncs.geturl           = pFuncs->geturl;
    NPNFuncs.posturlnotify    = pFuncs->posturlnotify;
    NPNFuncs.posturl          = pFuncs->posturl;
    NPNFuncs.requestread      = pFuncs->requestread;
    NPNFuncs.newstream        = pFuncs->newstream;
    NPNFuncs.write            = pFuncs->write;
    NPNFuncs.destroystream    = pFuncs->destroystream;
    NPNFuncs.status           = pFuncs->status;
    NPNFuncs.uagent           = pFuncs->uagent;
    NPNFuncs.memalloc         = pFuncs->memalloc;
    NPNFuncs.memfree          = pFuncs->memfree;
    NPNFuncs.memflush         = pFuncs->memflush;
    NPNFuncs.reloadplugins    = pFuncs->reloadplugins;
    NPNFuncs.getJavaEnv       = pFuncs->getJavaEnv;
    NPNFuncs.getJavaPeer      = pFuncs->getJavaPeer;
    NPNFuncs.getvalue         = pFuncs->getvalue;
    NPNFuncs.setvalue         = pFuncs->setvalue;
    NPNFuncs.invalidaterect   = pFuncs->invalidaterect;
    NPNFuncs.invalidateregion = pFuncs->invalidateregion;
    NPNFuncs.forceredraw      = pFuncs->forceredraw;*/

    // Success
    MessageBoxA(0, "NP_Initialize", "Log", 0);
    return NPERR_NO_ERROR;

}

Exported void NP_Shutdown() {

    MessageBoxA(0, "NP_Shutdown", "Log", 0);

}

    /* Entry points */
    NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* savedData) {

        MessageBoxA(0, "NPP_New", "Log", 0);
        return NPERR_NO_ERROR;

    }

    NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) {

        MessageBoxA(0, "NPP_GetValue", "Log", 0);
        return NPERR_NO_ERROR;

    }

    /*** Omitted... All the other functions are here, with just a MessageBox call in them ***/

Exported NPError NP_GetEntryPoints(NPPluginFuncs* pFuncs) {

    if (pFuncs == NULL)
        return NPERR_INVALID_FUNCTABLE_ERROR;

    if (pFuncs->size < sizeof(NPPluginFuncs))
        return NPERR_INVALID_FUNCTABLE_ERROR;

    pFuncs->size                = sizeof(NPPluginFuncs);
    pFuncs->version             = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
    pFuncs->newp                = &NPP_New;
    pFuncs->destroy             = &NPP_Destroy;
    pFuncs->setwindow           = &NPP_SetWindow;
    pFuncs->newstream           = &NPP_NewStream;
    pFuncs->destroystream       = &NPP_DestroyStream;
    pFuncs->asfile              = &NPP_StreamAsFile;
    pFuncs->writeready          = &NPP_WriteReady;
    pFuncs->write               = &NPP_Write;
    pFuncs->print               = &NPP_Print;
    pFuncs->event               = &NPP_HandleEvent;
    pFuncs->urlnotify           = &NPP_URLNotify;
    pFuncs->getvalue            = &NPP_GetValue;
    pFuncs->setvalue            = &NPP_SetValue;
    pFuncs->javaClass           = NULL;
    pFuncs->gotfocus            = &NPP_GotFocus;
    pFuncs->lostfocus           = &NPP_LostFocus;
    pFuncs->urlredirectnotify   = &NPP_URLRedirectNotify;
    pFuncs->clearsitedata       = &NPP_ClearSiteData;
    pFuncs->getsiteswithdata    = &NPP_GetSitesWithData;

    MessageBoxA(0, "NP_GetEntryPoints", "Log", 0);
    return NPERR_NO_ERROR;

}

I added a MessageBox call to every function, so I can see if the right functions are being called. When I run my test page, which is a blank page with an <embed> tag in it, I get a message saying NP_GetEntryPoints, then one saying NP_Initialize, then Chrome pops up a bar saying that my plugin has crashed. I think the problem is in my NP_GetEntryPoints, but I just can't see it... Is there anything I'm doing wrong, or forgetting to do?

I compile with :

g++.exe -DWIN32 -D_WIN32 -D_WINDOWS -D_WIN32_WINNT=0x0600 -D_WIN32_IE=0x0600 -D_UNICODE -DUNICODE -static-libgcc -static-libstdc++ -c "main.cpp" -o main.o

and

windres.exe "resource.rc" "resource.o"

and I link into a .DLL with :

g++.exe -Wl,--subsystem,windows -o "npplugin.dll" -s -shared main.o resource.o -lcomctl32 -lws2_32 -luxtheme -lgdi32 -lshell32 -lshlwapi

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

水水月牙 2024-12-18 09:03:49

函数表之间的大小因浏览器和浏览器版本而异。

您根据硬编译的库标头检查大小:

if (pFuncs->size < sizeof(NPNetscapeFuncs))
    return NPERR_INVALID_FUNCTABLE_ERROR;

这可能是问题所在。
例如,最新的(在编写 gecko xulrunner SDK 时包含一个 84 字节大小的结构:

typedef struct _NPPluginFuncs {
  uint16_t size;
  uint16_t version;
  NPP_NewProcPtr newp;
  NPP_DestroyProcPtr destroy;
  NPP_SetWindowProcPtr setwindow;
  NPP_NewStreamProcPtr newstream;
  NPP_DestroyStreamProcPtr destroystream;
  NPP_StreamAsFileProcPtr asfile;
  NPP_WriteReadyProcPtr writeready;
  NPP_WriteProcPtr write;
  NPP_PrintProcPtr print;
  NPP_HandleEventProcPtr event;
  NPP_URLNotifyProcPtr urlnotify;
  void* javaClass;
  NPP_GetValueProcPtr getvalue;
  NPP_SetValueProcPtr setvalue;
  NPP_GotFocusPtr gotfocus;
  NPP_LostFocusPtr lostfocus;
  NPP_URLRedirectNotifyPtr urlredirectnotify;
  NPP_ClearSiteDataPtr clearsitedata;
  NPP_GetSitesWithDataPtr getsiteswithdata;
  NPP_DidCompositePtr didComposite;
} NPPluginFuncs;

Chrome 发送一个 80 字节的结构。

所以我猜最后一个函数指针不在 chrome 使用的结构中。

The size between function tables differs between browsers and version of browsers.

You check the size against your hard compiled library headers:

if (pFuncs->size < sizeof(NPNetscapeFuncs))
    return NPERR_INVALID_FUNCTABLE_ERROR;

This can be the problem.
For example the latest (at the moment of writing gecko xulrunner SDK contains a 84 byte size struct:

typedef struct _NPPluginFuncs {
  uint16_t size;
  uint16_t version;
  NPP_NewProcPtr newp;
  NPP_DestroyProcPtr destroy;
  NPP_SetWindowProcPtr setwindow;
  NPP_NewStreamProcPtr newstream;
  NPP_DestroyStreamProcPtr destroystream;
  NPP_StreamAsFileProcPtr asfile;
  NPP_WriteReadyProcPtr writeready;
  NPP_WriteProcPtr write;
  NPP_PrintProcPtr print;
  NPP_HandleEventProcPtr event;
  NPP_URLNotifyProcPtr urlnotify;
  void* javaClass;
  NPP_GetValueProcPtr getvalue;
  NPP_SetValueProcPtr setvalue;
  NPP_GotFocusPtr gotfocus;
  NPP_LostFocusPtr lostfocus;
  NPP_URLRedirectNotifyPtr urlredirectnotify;
  NPP_ClearSiteDataPtr clearsitedata;
  NPP_GetSitesWithDataPtr getsiteswithdata;
  NPP_DidCompositePtr didComposite;
} NPPluginFuncs;

Chrome sends in a 80 byte struct.

So I guess the last function pointer is not in the struct used by chrome.

彡翼 2024-12-18 09:03:49

我建议使用某种形式的日志记录而不是消息框;您是否尝试过删除受到攻击的消息框,看看是否可以进一步? Chrome 在进程外启动插件,因此它会期望这些入口点及时完成,否则它可能会杀死插件。

另外,--plugin-startup-dialog 选项在某些情况下可能很有用,这样您就可以确定插件何时启动;另外,如果您想附加调试器并看看是否可以通过这种方式找到更多信息,它可能会很有用。仅供参考。我也尝试在 Firefox 中加载它;有时在另一个浏览器中加载插件会提供不同的信息。如果它适用于其中一种而不适用于另一种,那也可以告诉您一些信息。

I would recommend using some form of logging rather than messageboxes; have you tried removing the messageboxes that are getting hit and see if you make it further? Chrome starts the plugin out of process, so it's going to expect those entrypoints to finish in a timely manner or else it'll likely kill the plugin.

Also, the --plugin-startup-dialog option may be useful to in in some cases just so you can see for sure when the plugin is starting; also, it may be useful if you wanted to attach a debugger and see if you can find more info that way. Just an FYI. I'd also try loading it in firefox; sometimes loading a plugin in another browser gives you different information. If it works in one and not the other, that can tell you something as well.

暮凉 2024-12-18 09:03:49

mm尝试将 NP_GetEntryPoints()

  pFuncs->newp                = &NPP_New;
  pFuncs->destroy             = &NPP_Destroy;

(...)

更改为

  pFuncs->newp                = NPP_New;
  pFuncs->destroy             = NPP_Destroy;

mm try to change in NP_GetEntryPoints()

  pFuncs->newp                = &NPP_New;
  pFuncs->destroy             = &NPP_Destroy;

(...)

to

  pFuncs->newp                = NPP_New;
  pFuncs->destroy             = NPP_Destroy;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文