Back to index

lightning-sunbird  0.9+nobinonly
ControlEventSink.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Adam Lock <adamlock@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "StdAfx.h"
00040 
00041 #include "ControlEventSink.h"
00042 
00043 CControlEventSink::CControlEventSink() :
00044     m_dwEventCookie(0),
00045     m_EventIID(GUID_NULL)
00046 {
00047 }
00048 
00049 CControlEventSink::~CControlEventSink()
00050 {
00051     UnsubscribeFromEvents();
00052 }
00053 
00054 BOOL
00055 CControlEventSink::GetEventSinkIID(IUnknown *pControl, IID &iid, ITypeInfo **typeInfo)
00056 {
00057        iid = GUID_NULL;
00058     if (!pControl)
00059     {
00060         return E_INVALIDARG;
00061     }
00062 
00063        // IProvideClassInfo2 way is easiest
00064 //    CComQIPtr<IProvideClassInfo2> classInfo2 = pControl;
00065 //    if (classInfo2)
00066 //    {
00067 //        classInfo2->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID, &iid);
00068 //        if (!::IsEqualIID(iid, GUID_NULL))
00069 //        {
00070 //            return TRUE;
00071 //        }
00072 //    }
00073 
00074     // Yuck, the hard way
00075     CComQIPtr<IProvideClassInfo> classInfo = pControl;
00076     if (!classInfo)
00077     {
00078         return FALSE;
00079     }
00080 
00081     // Search the class type information for the default source interface
00082     // which is the outgoing event sink.
00083 
00084     CComPtr<ITypeInfo> classTypeInfo;
00085     classInfo->GetClassInfo(&classTypeInfo);
00086     if (!classTypeInfo)
00087     {
00088         return FALSE;
00089     }
00090     TYPEATTR *classAttr = NULL;
00091     if (FAILED(classTypeInfo->GetTypeAttr(&classAttr)))
00092     {
00093         return FALSE;
00094     }
00095     INT implFlags = 0;
00096     for (UINT i = 0; i < classAttr->cImplTypes; i++)
00097     {
00098         // Search for the interface with the [default, source] attr
00099         if (SUCCEEDED(classTypeInfo->GetImplTypeFlags(i, &implFlags)) &&
00100             implFlags == (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE))
00101         {
00102             CComPtr<ITypeInfo> eventSinkTypeInfo;
00103             HREFTYPE hRefType;
00104             if (SUCCEEDED(classTypeInfo->GetRefTypeOfImplType(i, &hRefType)) &&
00105                 SUCCEEDED(classTypeInfo->GetRefTypeInfo(hRefType, &eventSinkTypeInfo)))
00106             {
00107                 TYPEATTR *eventSinkAttr = NULL;
00108                 if (SUCCEEDED(eventSinkTypeInfo->GetTypeAttr(&eventSinkAttr)))
00109                 {
00110                     iid = eventSinkAttr->guid;
00111                     if (typeInfo)
00112                     {
00113                         *typeInfo = eventSinkTypeInfo.p;
00114                         (*typeInfo)->AddRef();
00115                     }
00116                     eventSinkTypeInfo->ReleaseTypeAttr(eventSinkAttr);
00117                 }
00118             }
00119             break;
00120         }
00121     }
00122     classTypeInfo->ReleaseTypeAttr(classAttr);
00123 
00124     return (!::IsEqualIID(iid, GUID_NULL));
00125 }
00126 
00127 void CControlEventSink::UnsubscribeFromEvents()
00128 {
00129     if (m_spEventCP)
00130     {
00131         // Unsubscribe and reset
00132         m_spEventCP->Unadvise(m_dwEventCookie);
00133         m_dwEventCookie = 0;
00134         m_spEventCP.Release();
00135     }
00136 }
00137 
00138 HRESULT CControlEventSink::SubscribeToEvents(IUnknown *pControl)
00139 {
00140     if (!pControl)
00141     {
00142         return E_INVALIDARG;
00143     }
00144 
00145     // Throw away any existing connections
00146     UnsubscribeFromEvents();
00147 
00148     // Grab the outgoing event sink IID which will be used to subscribe
00149     // to events via the connection point container.
00150 
00151     IID iidEventSink;
00152     CComPtr<ITypeInfo> typeInfo;
00153     if (!GetEventSinkIID(pControl, iidEventSink, &typeInfo))
00154     {
00155         return E_FAIL;
00156     }
00157 
00158     // Get the connection point
00159     CComQIPtr<IConnectionPointContainer> ccp = pControl;
00160     CComPtr<IConnectionPoint> cp;
00161     if (!ccp)
00162     {
00163         return E_FAIL;
00164     }
00165 
00166     // Custom IID
00167     m_EventIID = iidEventSink;
00168     DWORD dwCookie = 0;
00169     if (!ccp ||
00170         FAILED(ccp->FindConnectionPoint(m_EventIID, &cp)) ||
00171         FAILED(cp->Advise(this, &m_dwEventCookie)))
00172     {
00173         return E_FAIL;
00174     }
00175 
00176     m_spEventCP = cp;
00177     m_dwEventCookie = dwCookie;
00178     m_spEventSinkTypeInfo = typeInfo;
00179     return S_OK;
00180 }
00181 
00182 HRESULT
00183 CControlEventSink::InternalInvoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
00184 {
00185     // Override me!
00186     return E_NOTIMPL;
00187 }
00188 
00190 // IDispatch implementation
00191 
00192 
00193 HRESULT STDMETHODCALLTYPE CControlEventSink::GetTypeInfoCount(/* [out] */ UINT __RPC_FAR *pctinfo)
00194 {
00195     return E_NOTIMPL;
00196 }
00197 
00198 
00199 HRESULT STDMETHODCALLTYPE CControlEventSink::GetTypeInfo(/* [in] */ UINT iTInfo, /* [in] */ LCID lcid, /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
00200 {
00201     return E_NOTIMPL;
00202 }
00203 
00204 
00205 HRESULT STDMETHODCALLTYPE CControlEventSink::GetIDsOfNames(/* [in] */ REFIID riid, /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames, /* [in] */ UINT cNames, /* [in] */ LCID lcid, /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
00206 {
00207     return E_NOTIMPL;
00208 }
00209 
00210 
00211 HRESULT STDMETHODCALLTYPE CControlEventSink::Invoke(/* [in] */ DISPID dispIdMember, /* [in] */ REFIID riid, /* [in] */ LCID lcid, /* [in] */ WORD wFlags, /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams, /* [out] */ VARIANT __RPC_FAR *pVarResult, /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo, /* [out] */ UINT __RPC_FAR *puArgErr)
00212 {
00213     return InternalInvoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
00214 }
00215 
00216