0
votes

I have to import a NPAPI DLL in a C++ application for my project. I follow the excellent tutorial : http://colonelpanic.net/2009/03/building-a-firefox-plugin-part-one/

However I have some trouble to access to the methods of the dll. (Note: in a browser the dll is completly functional). After calling the main functions : NP_GetEntryPoints and NP_Initialize and retrieving the ScriptableNPObject, the invocation of the methods return no value with no error. The property or method names are the same used in javascript in the browser (functional case).

For information, the property and method names and the mime-type have been replaced in this sample.

Anyone has an idea to invoke the methods of the dll by simulating what the browser does?

Here is a part of the main program:

if (hDLL == 0)
{
    std::cout << "DLL failed to load!" << std::endl;
}
else
{
    std::cout << "DLL loaded!" << std::endl;

    //WRAP NP_GETENTRYPOINTS FUNCTION:
    _GetEntryPointsFunc = (GetEntryPointsFunc)GetProcAddress(hDLL, "NP_GetEntryPoints");
    if (_GetEntryPointsFunc)
    {
        std::cout << "Get NP_GetEntryPoints Function!" << std::endl;
        status = _GetEntryPointsFunc(pFuncs);

    }

    //WRAP NP_INITIALIZE FUNCTION:
    _InitializeFunc = (InitializeFunc)GetProcAddress(hDLL, "NP_Initialize");
    if (_InitializeFunc)
    {   
        std::cout << "Get NP_Initialize Function!" << std::endl;
        status = _InitializeFunc(&sBrowserFuncs);
    }


    int32_t       mode = NP_EMBED; 
    int32_t       argc = 7;
    static const char mimetype[] = "application/x-mime_type_of_my_plugin";

    char * argn[] = {"param1", "param2", "param3", "param4", "param5", "param6", "param7"};
    char * argv[] = { "value1", "value2", "value3", "value4", "value5", "value6", "value7" };



    NPObject np_object;
    uint16_t size;
    char* descritpionString;
    char* nameString;

  instance = &(plugin_instance.mNPP);
    status = pFuncs->newp((char*)mimetype, instance, (uint16_t)mode, argc, argn, argv, &saved);
    status = pFuncs->version; //OK  
    status = pFuncs->getvalue(instance,NPPVpluginDescriptionString,&descritpionString); //OK
    status = pFuncs->getvalue(instance,NPPVpluginNameString,&nameString); //OK

    status = pFuncs->getvalue(instance,NPPVpluginScriptableNPObject,&np_object); //ISSUE STARTS HERE

    std::cin.get();

}

Here is my create_object function called after getting the scriptable NPObject with the getvalue function:

NPObject* _createobject(NPP npp, NPClass* aClass)
{

if (!npp) {
    return nullptr;
}

if (!aClass) {
    return nullptr;
}

NPObject *npobj;

if (aClass->allocate) {
    npobj = aClass->allocate(npp, aClass);
} else {
    npobj = (NPObject *)malloc(sizeof(NPObject));
}

if (npobj) {
    npobj->_class = aClass;
    npobj->referenceCount = 1;

    //TEST:
            NPError status;
    NPString url;
    NPVariant result;
    NPVariant variant;
    NPIdentifier property = "existing_property";
    NPIdentifier *arrayId;
    uint32_t count = 2;

    const char *str = "https://test_url.com";
    url.UTF8Characters = str;//;
    url.UTF8Length = 20;

    variant.type = NPVariantType_String;
    variant.value.stringValue = url;
    NPVariant args[] = { variant };

    status = 1; //GENERIC ERROR VALUE
    status = npobj->_class->structVersion; //OK
    status = npobj->_class->hasMethod(npobj,L"existing_set_function"); //STATUS OK
    status = npobj->_class->enumerate(npobj, &arrayId, &count); //Privileged instruction ERROR
    status = npobj->_class->hasProperty(npobj, property); //STATUS OK
    status = npobj->_class->getProperty(npobj, property, &result); //STATUS OK BUT NO RESULT
    status = npobj->_class->invoke(npobj,L"existing_set_function",args,1,&result); //STATUS OK
    status = npobj->_class->invoke(npobj,L"existing_get_function",args,0,&result); //STATUS OK BUT NO RESULT
    status = npobj->_class->invokeDefault(npobj,args,0,&result); //STATUS OK BUT NO RESULT
    //END TEST
}
return npobj;
}

Finally, here is the plugin_instance methods to declare ndata and pdata:

nsNPAPIPluginInstance::nsNPAPIPluginInstance()
{
  mNPP.pdata = NULL;
  mNPP.ndata = this;
}

nsNPAPIPluginInstance::~nsNPAPIPluginInstance()
{

}

Thanks in advance.

1

1 Answers

0
votes

While it is unclear what "no result" means, a privileged instruction error suggests the function pointer is off.

I'd start with:

  • Checking that structVersion >= NP_CLASS_STRUCT_VERSION_ENUM (otherwise NPClass::enumerate is not available)
  • Using the proper npapi-sdk headers - your function pointer type names suggest you are not doing that
  • Using a simple test plugin to see what happens on the plugin side
  • Take care that the NPIdentifiers match up between your host application and the plugin, i.e. use a common string->NPIdentifier mapping for the host code and NPN_GetStringIdentifier() - as posted this can't work
  • Don't test the NPObject right in the creation function - the plugin may set things up to work properly only after NPN_CreateObject() returned