NS_IMETHODIMP PyG_Base::QueryInterface(REFNSIID iid, void** ppv) { #ifdef PYXPCOM_DEBUG_FULL { char *sziid = iid.ToString(); LogF("PyGatewayBase::QueryInterface: %s", sziid); Allocator::Free(sziid); } #endif NS_PRECONDITION(ppv, "NULL pointer"); if (ppv==nsnull) return NS_ERROR_NULL_POINTER; *ppv = nsnull; // If one of our native interfaces (but NOT nsISupports if we have a base) // return this. // It is important is that nsISupports come from the base object // to ensure that we live by XPCOM identity rules (other interfaces need // not abide by this rule - only nsISupports.) if ( (m_pBaseObject==NULL || !iid.Equals(NS_GET_IID(nsISupports))) && (*ppv=ThisAsIID(iid)) != NULL ) { AddRef(); return NS_OK; } // If we have a "base object", then we need to delegate _every_ remaining // QI to it. if (m_pBaseObject != NULL) return m_pBaseObject->QueryInterface(iid, ppv); // Call the Python policy to see if it (says it) supports the interface PRBool supports = PR_FALSE; { // temp scope for Python lock CEnterLeavePython celp; PyObject * ob = Py_nsIID::PyObjectFromIID(iid); // must say this is an 'internal' call, else we recurse QI into // oblivion. PyObject * this_interface_ob = Py_nsISupports::PyObjectFromInterface( (nsXPTCStubBase *)this, iid, PR_FALSE, PR_TRUE); if ( !ob || !this_interface_ob) { Py_XDECREF(ob); Py_XDECREF(this_interface_ob); return NS_ERROR_OUT_OF_MEMORY; } PyObject *result = PyObject_CallMethod(m_pPyObject, (char*)"_QueryInterface_", (char*)"OO", this_interface_ob, ob); Py_DECREF(ob); Py_DECREF(this_interface_ob); if ( result ) { if (Py_nsISupports::InterfaceFromPyObject(result, iid, (nsISupports **)ppv, PR_TRUE)) { // If OK, but NULL, _QI_ returned None, which simply means // "no such interface" supports = (*ppv!=NULL); // result has been QI'd and AddRef'd all ready for return. } else { // Dump this message and any Python exception before // reporting the fact that QI failed - this error // may provide clues! PyXPCOM_LogError("The _QueryInterface_ method returned an object of type '%s', but an interface was expected\n", result->ob_type->tp_name); // supports remains false } Py_DECREF(result); } else { NS_ABORT_IF_FALSE(PyErr_Occurred(), "Got NULL result, but no Python error flagged!"); NS_WARN_IF_FALSE(!supports, "Have failure with success flag set!"); PyXPCOM_LogError("The _QueryInterface_ processing failed.\n"); // supports remains false. // We have reported the error, and are returning to COM, // so we should clear it. PyErr_Clear(); } } // end of temp scope for Python lock - lock released here! if ( !supports ) return NS_ERROR_NO_INTERFACE; return NS_OK; }