AgileReference::AgileReference(REFIID aIid, IUnknown* aObject) : mIid(aIid) , mGitCookie(0) { /* * There are two possible techniques for creating agile references. Starting * with Windows 8.1, we may use the RoGetAgileReference API, which is faster. * If that API is not available, we fall back to using the Global Interface * Table. */ static const DynamicallyLinkedFunctionPtr<decltype(&::RoGetAgileReference)> pRoGetAgileReference(L"ole32.dll", "RoGetAgileReference"); MOZ_ASSERT(aObject); if (pRoGetAgileReference && SUCCEEDED(pRoGetAgileReference(AGILEREFERENCE_DEFAULT, aIid, aObject, getter_AddRefs(mAgileRef)))) { return; } IGlobalInterfaceTable* git = ObtainGit(); MOZ_ASSERT(git); if (!git) { return; } DebugOnly<HRESULT> hr = git->RegisterInterfaceInGlobal(aObject, aIid, &mGitCookie); MOZ_ASSERT(SUCCEEDED(hr)); }
PyObject *PyIGlobalInterfaceTable::GetInterfaceFromGlobal(PyObject *self, PyObject *args) { PyObject *obriid = NULL; DWORD dwCookie; IID riid; void* ppv; HRESULT hr; IGlobalInterfaceTable *pIGIT = GetI(self); if ( pIGIT == NULL ) { return NULL; } if (!PyArg_ParseTuple(args, "lO:GetInterfaceFromGlobal", &dwCookie, &obriid) ) { return NULL; } BOOL bPythonIsHappy = TRUE; if (!PyWinObject_AsIID(obriid, &riid)) bPythonIsHappy = FALSE; if(!bPythonIsHappy) { return NULL; } PY_INTERFACE_PRECALL; hr = pIGIT->GetInterfaceFromGlobal( dwCookie, riid, &ppv ); PY_INTERFACE_POSTCALL; if ( FAILED(hr) ) { return PyCom_BuildPyException(hr, pIGIT, IID_IGlobalInterfaceTable ); } return PyCom_PyObjectFromIUnknown((IUnknown*)ppv, riid, FALSE); }
AgileReference::~AgileReference() { if (!mGitCookie) { return; } IGlobalInterfaceTable* git = ObtainGit(); MOZ_ASSERT(git); if (!git) { return; } DebugOnly<HRESULT> hr = git->RevokeInterfaceFromGlobal(mGitCookie); MOZ_ASSERT(SUCCEEDED(hr)); }
HRESULT AgileReference::Resolve(REFIID aIid, void** aOutInterface) { MOZ_ASSERT(aOutInterface); MOZ_ASSERT(mAgileRef || mGitCookie); if (!aOutInterface) { return E_INVALIDARG; } *aOutInterface = nullptr; if (mAgileRef) { // IAgileReference lets you directly resolve the interface you want... return mAgileRef->Resolve(aIid, aOutInterface); } if (!mGitCookie) { return E_UNEXPECTED; } IGlobalInterfaceTable* git = ObtainGit(); MOZ_ASSERT(git); if (!git) { return E_UNEXPECTED; } RefPtr<IUnknown> originalInterface; HRESULT hr = git->GetInterfaceFromGlobal(mGitCookie, mIid, getter_AddRefs(originalInterface)); if (FAILED(hr)) { return hr; } if (aIid == mIid) { originalInterface.forget(aOutInterface); return S_OK; } // ...Whereas the GIT requires us to obtain the same interface that we // requested and then QI for the desired interface afterward. return originalInterface->QueryInterface(aIid, aOutInterface); }
PyObject *PyIGlobalInterfaceTable::RegisterInterfaceInGlobal(PyObject *self, PyObject *args) { PyObject *obpUnk = NULL; PyObject *obriid = NULL; IUnknown * pUnk; IID riid; DWORD pdwCookie; PyObject *ppyobRetval = NULL; HRESULT hr; IGlobalInterfaceTable *pIGIT = GetI(self); if ( pIGIT == NULL ) { return NULL; } if (!PyArg_ParseTuple(args, "OO:RegisterInterfaceInGlobal", &obpUnk, &obriid) ) { return NULL; } BOOL bPythonIsHappy = TRUE; if (!PyCom_InterfaceFromPyInstanceOrObject(obpUnk, IID_IUnknown, (void **)&pUnk, TRUE /* bNoneOK */)) bPythonIsHappy = FALSE; if (!PyWinObject_AsIID(obriid, &riid)) bPythonIsHappy = FALSE; if(!bPythonIsHappy) { return NULL; } PY_INTERFACE_PRECALL; hr = pIGIT->RegisterInterfaceInGlobal( pUnk, riid, &pdwCookie ); if (pUnk) pUnk->Release(); PY_INTERFACE_POSTCALL; if ( FAILED(hr) ) { return PyCom_BuildPyException(hr, pIGIT, IID_IGlobalInterfaceTable ); } ppyobRetval = Py_BuildValue("l", pdwCookie); return ppyobRetval; }
PyObject *PyIGlobalInterfaceTable::RevokeInterfaceFromGlobal(PyObject *self, PyObject *args) { DWORD dwCookie; HRESULT hr; IGlobalInterfaceTable *pIGIT = GetI(self); if ( pIGIT == NULL ) { return NULL; } if (!PyArg_ParseTuple(args, "l:RevokeInterfaceFromGlobal", &dwCookie) ) { return NULL; } PY_INTERFACE_PRECALL; hr = pIGIT->RevokeInterfaceFromGlobal( dwCookie ); PY_INTERFACE_POSTCALL; if ( FAILED(hr) ) { return PyCom_BuildPyException(hr, pIGIT, IID_IGlobalInterfaceTable ); } Py_INCREF(Py_None); return Py_None; }