static void test_source_iface(void) { unsigned short maj_ver, min_ver; IID libid, iid; HRESULT hres; support_classinfo2 = TRUE; maj_ver = min_ver = 0xdead; hres = AtlGetObjectSourceInterface((IUnknown*)&Dispatch, &libid, &iid, &maj_ver, &min_ver); ok(hres == S_OK, "AtlGetObjectSourceInterface failed: %08x\n", hres); ok(IsEqualGUID(&libid, &LIBID_MSHTML), "libid = %s\n", debugstr_guid(&libid)); ok(IsEqualGUID(&iid, &DIID_DispHTMLBody), "iid = %s\n", debugstr_guid(&iid)); ok(maj_ver == 4 && min_ver == 0, "ver = %d.%d\n", maj_ver, min_ver); support_classinfo2 = FALSE; persist_clsid = CLSID_HTMLDocument; maj_ver = min_ver = 0xdead; hres = AtlGetObjectSourceInterface((IUnknown*)&Dispatch, &libid, &iid, &maj_ver, &min_ver); ok(hres == S_OK, "AtlGetObjectSourceInterface failed: %08x\n", hres); ok(IsEqualGUID(&libid, &LIBID_MSHTML), "libid = %s\n", debugstr_guid(&libid)); ok(IsEqualGUID(&iid, &DIID_HTMLDocumentEvents), "iid = %s\n", debugstr_guid(&iid)); ok(maj_ver == 4 && min_ver == 0, "ver = %d.%d\n", maj_ver, min_ver); persist_clsid = CLSID_HTMLStyle; maj_ver = min_ver = 0xdead; hres = AtlGetObjectSourceInterface((IUnknown*)&Dispatch, &libid, &iid, &maj_ver, &min_ver); ok(hres == S_OK, "AtlGetObjectSourceInterface failed: %08x\n", hres); ok(IsEqualGUID(&libid, &LIBID_MSHTML), "libid = %s\n", debugstr_guid(&libid)); ok(IsEqualGUID(&iid, &IID_NULL), "iid = %s\n", debugstr_guid(&iid)); ok(maj_ver == 4 && min_ver == 0, "ver = %d.%d\n", maj_ver, min_ver); }
HRESULT CJSExtender::SinkObject(CString strPrefix, IDispatch *pUnk, LCID lcid) { if (!pUnk || strPrefix==_T("")) return E_INVALIDARG; HRESULT hr = S_FALSE; GUID iid = GUID_NULL; if (theApp.m_pEventProxy) theApp.m_pEventProxy->GetConnectionInterface(&iid); else { CComQIPtr<IConnectionPointContainer> pContainer(pUnk); if (pContainer == nullptr) return 0; GUID libid; WORD wMajorVer = 1; WORD wMinorVer = 0; hr = AtlGetObjectSourceInterface(pUnk, &libid, &iid, &wMajorVer, &wMinorVer); if (iid == GUID_NULL) { IConnectionPoint* pConnectionPoint = nullptr; IEnumConnectionPoints* pEnum = nullptr; HRESULT hr = pContainer->EnumConnectionPoints(&pEnum); if (pEnum) { ULONG uFetched; while (S_OK == (pEnum->Next(1, &pConnectionPoint, &uFetched)) && uFetched >= 1) { hr = pConnectionPoint->GetConnectionInterface(&iid); if (hr == S_OK) { pConnectionPoint->Release(); pConnectionPoint = nullptr; break; } pConnectionPoint->Release(); pConnectionPoint = nullptr; } pEnum->Release(); } } } if (iid != GUID_NULL) new CJSProxyObj(this, pUnk, iid, strPrefix); return S_OK; }
STDMETHODIMP CDispCtl::Connect() { if(!m_bConnected){ HRESULT hr = CoCreateInstance(CLSID_DispServ, NULL, CLSCTX_ALL ,IID_IDispServ, (void **)&m_pIServ); AtlGetObjectSourceInterface(m_pIServ, &m_libid, &m_iid, &m_wMajorVerNum, &m_wMinorVerNum); hr = DispEventAdvise(m_pIServ, &m_iid); if(hr == S_OK) { m_bConnected = TRUE; SysFreeString(m_OutText.bstrVal); m_OutText.bstrVal = SysAllocString(L"Connected"); FireViewChange(); } return hr; } return S_OK; }
STDMETHODIMP CDispEventTransfer::attachEvent( IDispatch* source, BSTR event, VARIANT notify, VARIANT listener, VARIANT_BOOL* pRetVal ) { if( pRetVal ) *pRetVal = VARIANT_FALSE; if( NULL == source || NULL == event || (VT_EMPTY==notify.vt||VT_NULL==notify.vt||VT_ERROR == notify.vt) && (VT_EMPTY==listener.vt||VT_NULL==listener.vt||VT_ERROR==listener.vt) ) return S_FALSE; UINT n = 0; HRESULT hr = source->GetTypeInfoCount( &n ); if( FAILED(hr) || n < 1 ) return S_FALSE; CComPtr<ITypeInfo> spTI; hr = source->GetTypeInfo( 0, LOCALE_USER_DEFAULT, &spTI ); if( FAILED(hr) || !spTI ) return S_FALSE; CComPtr<ITypeLib> spTL; UINT index = 0; hr = spTI->GetContainingTypeLib( &spTL, &index ); if( FAILED(hr) || !spTL ) return S_FALSE; hr = AtlGetObjectSourceInterface( source, &m_libid, &m_iid, &m_wMajorVerNum, &m_wMinorVerNum ); if( FAILED(hr) || IID_NULL == m_iid ) return S_FALSE; CComPtr<ITypeInfo> spTI2; hr = spTL->GetTypeInfoOfGuid( m_iid, &spTI2 ); if( FAILED(hr) || !spTI2 ) return S_FALSE; MEMBERID idMember = DISPID_UNKNOWN; hr = spTI2->GetIDsOfNames( &event, 1, &idMember ); if( FAILED(hr) || DISPID_UNKNOWN == idMember ) return S_FALSE; hr = Advise( source ); if( FAILED(hr) ) return S_FALSE; m_spSource = source; m_bstrEvent = event; m_idMember = idMember; m_vNotify = notify; m_vListener = listener; if( pRetVal ) *pRetVal = VARIANT_TRUE; return S_OK; }
int _tmain(int argc, _TCHAR* argv[]) { HRESULT hr; // Initializes the COM library on the current thread and identifies the // concurrency model as single-thread apartment (STA). ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); ///////////////////////////////////////////////////////////////////////// // Create the ATLDllCOMServer.SimpleObject COM object using the // #import directive and smart pointers. // CComQIPtr<ISimpleObject> spSimpleObj; hr = spSimpleObj.CoCreateInstance(OLESTR( "ATLDllCOMServer.SimpleObject")); if (FAILED(hr)) { _tprintf(_T( "ISimpleObjectPtr.CoCreateInstance failed w/err 0x%08lx\n" ), hr); return hr; } ///////////////////////////////////////////////////////////////////////// // Use sink object 1 (CATLSimpleSinkObject1) to set up the sink for the // events of the source COM object. // _putts(_T("Create sink object 1")); // Construct the sink object CATLSimpleSinkObject1 defined in // ATLSimpleSinkObject.h CATLSimpleSinkObject1* pSinkObj1 = new CATLSimpleSinkObject1(); // Make sure the COM object corresponding to pUnk implements // IProvideClassInfo2 or IPersist*. Call this method to extract info // about source type library if you specified only 2 parameters to // IDispEventImpl. hr = AtlGetObjectSourceInterface(spSimpleObj, &pSinkObj1->m_libid, &pSinkObj1->m_iid, &pSinkObj1->m_wMajorVerNum, &pSinkObj1->m_wMinorVerNum); _ASSERTE(SUCCEEDED(hr)); // Connect the sink and source, spSimpleObj is the source COM object hr = pSinkObj1->DispEventAdvise(spSimpleObj, &pSinkObj1->m_iid); _ASSERTE(SUCCEEDED(hr)); // Invoke the source COM object { // Set FloatProperty which fires the event FloatPropertyChanging _tprintf(_T("Set FloatProperty = %.2f\n"), 1.1f); spSimpleObj->PutFloatProperty(1.1f); float fProp = spSimpleObj->GetFloatProperty(); _tprintf(_T("Get FloatProperty = %.2f\n"), fProp); } // Disconnect from the source COM object if connected if (pSinkObj1->m_dwEventCookie != 0xFEFEFEFE) pSinkObj1->DispEventUnadvise(spSimpleObj, &pSinkObj1->m_iid); // Destroy the sink object delete pSinkObj1; ///////////////////////////////////////////////////////////////////////// // Use sink object 2 (CATLSimpleSinkObject2) to set up the sink for the // events of the source COM object. // _putts(_T("Create sink object 2")); // Construct the sink object CATLSimpleSinkObject2 defined in // ATLSimpleSinkObject.h CATLSimpleSinkObject2* pSinkObj2 = new CATLSimpleSinkObject2(); // Connect the sink and source, m_spSrcObj is the source COM object hr = pSinkObj2->DispEventAdvise(spSimpleObj); _ASSERTE(SUCCEEDED(hr)); // Invoke the source COM object { // Set FloatProperty which fires the event FloatPropertyChanging _tprintf(_T("Set FloatProperty = %.2f\n"), 1.2f); spSimpleObj->PutFloatProperty(1.2f); float fProp = spSimpleObj->GetFloatProperty(); _tprintf(_T("Get FloatProperty = %.2f\n"), fProp); } // Disconnect from source if connected if (pSinkObj2->m_dwEventCookie != 0xFEFEFEFE) pSinkObj2->DispEventUnadvise(spSimpleObj); // Destroy the sink object delete pSinkObj2; ///////////////////////////////////////////////////////////////////////// // Use sink object 3 (CATLSimpleSinkObject3) to set up the sink for the // events of the source COM object. // _putts(_T("Create sink object 3")); // Construct the sink object CATLSimpleSinkObject3 defined in // ATLSimpleSinkObject.h CATLSimpleSinkObject3* pSinkObj3 = new CATLSimpleSinkObject3(); // Connect the sink and source, m_spSrcObj is the source COM object hr = pSinkObj3->DispEventAdvise(spSimpleObj); _ASSERTE(SUCCEEDED(hr)); // Invoke the source COM object { // Set FloatProperty which fires the event FloatPropertyChanging _tprintf(_T("Set FloatProperty = %.2f\n"), 1.3f); spSimpleObj->PutFloatProperty(1.3f); float fProp = spSimpleObj->GetFloatProperty(); _tprintf(_T("Get FloatProperty = %.2f\n"), fProp); } // Disconnect from source if connected if (pSinkObj3->m_dwEventCookie != 0xFEFEFEFE) pSinkObj3->DispEventUnadvise(spSimpleObj); // Destroy the sink object delete pSinkObj3; ///////////////////////////////////////////////////////////////////////// // Release the COM object. // // Make sure that the source COM object is release before CoUninitialize spSimpleObj.Release(); // Uninitialize COM for this thread ::CoUninitialize(); return 0; }