⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 autoobj.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    return AddSink(pv, pdwCookie);
}

//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::AddSink
//=--------------------------------------------------------------------------=
// in some cases, we'll already have done the QI, and won't need to do the
// work that is done in the Advise routine above.  thus, these people can
// just call this instead. [this stems really from IQuickActivate]
//
// Parameters:
//    void *        - [in]  the sink to add. it's already been addref'd
//    DWORD *       - [out] cookie
//
// Output:
//    HRESULT
//
// Notes:
//
HRESULT CAutomationObjectWEvents::CConnectionPoint::AddSink
(
    void  *pv,
    DWORD *pdwCookie
)
{
    IUnknown **rgUnkNew;

    // we optimize the case where there is only one sink to not allocate
    // any storage.  turns out very rarely is there more than one.
    //
    switch (m_cSinks) {

        case 0:
            ASSERT(!m_rgSinks, L"this should be null when there are no sinks");
            m_rgSinks = (IUnknown **)pv;
            break;

        case 1:
            // go ahead and do the initial allocation.  we'll get 8 at a time
            //
            rgUnkNew = (IUnknown **)HeapAlloc(g_hHeap, 0, 8 * sizeof(IUnknown *));
            RETURN_ON_NULLALLOC(rgUnkNew);
            rgUnkNew[0] = (IUnknown *)m_rgSinks;
            rgUnkNew[1] = (IUnknown *)pv;
            m_rgSinks = rgUnkNew;
            break;

        default:
            // if we're out of sinks, then we have to increase the size
            // of the array
            //
            if (!(m_cSinks & 0x7)) {
                rgUnkNew = (IUnknown **)HeapReAlloc(g_hHeap, 0, m_rgSinks, (m_cSinks + 8) * sizeof(IUnknown *));
                RETURN_ON_NULLALLOC(rgUnkNew);
                m_rgSinks = rgUnkNew;
            } else
                rgUnkNew = m_rgSinks;

            rgUnkNew[m_cSinks] = (IUnknown *)pv;
            break;
    }

    *pdwCookie = (DWORD)pv;
    m_cSinks++;
    return S_OK;
}


//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::Unadvise
//=--------------------------------------------------------------------------=
// they don't want to be told any more.
//
// Parameters:
//    DWORD        - [in]  the cookie we gave 'em.
//
// Output:
//    HRESULT
//
// Notes:
//
STDMETHODIMP CAutomationObjectWEvents::CConnectionPoint::Unadvise
(
    DWORD dwCookie
)
{
    IUnknown *pUnk;
    int       x;

    if (!dwCookie)
        return S_OK;

    // see how many sinks we've currently got, and deal with things based
    // on that.
    //
    switch (m_cSinks) {
        case 1:
            // it's the only sink.  make sure the ptrs are the same, and
            // then free things up
            //
            if ((DWORD)m_rgSinks != dwCookie)
                return CONNECT_E_NOCONNECTION;
            m_rgSinks = NULL;
            break;

        case 2:
            // there are two sinks.  go back down to one sink scenario
            //
            if ((DWORD)m_rgSinks[0] != dwCookie && (DWORD)m_rgSinks[1] != dwCookie)
                return CONNECT_E_NOCONNECTION;

            pUnk = ((DWORD)m_rgSinks[0] == dwCookie)
                   ? m_rgSinks[1]
                   : ((DWORD)m_rgSinks[1] == dwCookie) ? m_rgSinks[0] : NULL;

            if (!pUnk) return CONNECT_E_NOCONNECTION;

            HeapFree(g_hHeap, 0, m_rgSinks);
            m_rgSinks = (IUnknown **)pUnk;
            break;

        default:
            // there are more than two sinks.  just clean up the hole we've
            // got in our array now.
            //
            for (x = 0; x < m_cSinks; x++) {
                if ((DWORD)m_rgSinks[x] == dwCookie)
                    break;
            }
            if (x == m_cSinks) return CONNECT_E_NOCONNECTION;
            if (x < m_cSinks - 1) 
                memcpy(&(m_rgSinks[x]), &(m_rgSinks[x + 1]), (m_cSinks -1 - x) * sizeof(IUnknown *));
            else
                m_rgSinks[x] = NULL;
            break;
    }


    // we're happy
    //
    m_cSinks--;
    ((IUnknown *)dwCookie)->Release();
    return S_OK;
}

//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::EnumConnections
//=--------------------------------------------------------------------------=
// enumerates all current connections
//
// Paramters:
//    IEnumConnections ** - [out] new enumerator object
//
// Output:
//    HRESULT
//
// NOtes:
//
STDMETHODIMP CAutomationObjectWEvents::CConnectionPoint::EnumConnections
(
    IEnumConnections **ppEnumOut
)
{
    CONNECTDATA *rgConnectData = NULL;
    int i;

    if (m_cSinks) {
        // allocate some memory big enough to hold all of the sinks.
        //
        rgConnectData = (CONNECTDATA *)HeapAlloc(g_hHeap, 0, m_cSinks * sizeof(CONNECTDATA));
        RETURN_ON_NULLALLOC(rgConnectData);

        // fill in the array
        //
        if (m_cSinks == 1) {
            rgConnectData[0].pUnk = (IUnknown *)m_rgSinks;
            rgConnectData[0].dwCookie = (DWORD)m_rgSinks;
        } else {
            // loop through all available sinks.
            //
            for (i = 0; i < m_cSinks; i++) {
                rgConnectData[i].pUnk = m_rgSinks[i];
                rgConnectData[i].dwCookie = (DWORD)m_rgSinks[i];
            }
        }
    }

    // create yon enumerator object.
    //
    *ppEnumOut = (IEnumConnections *)(IEnumGeneric *)new CStandardEnum(IID_IEnumConnections,
                        m_cSinks, sizeof(CONNECTDATA), rgConnectData, CopyAndAddRefObject);
    if (!*ppEnumOut) {
        HeapFree(g_hHeap, 0, rgConnectData);
        return E_OUTOFMEMORY;
    }

    return S_OK;
}

//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::~CConnectionPoint
//=--------------------------------------------------------------------------=
// cleans up
//
// Notes:
//
CAutomationObjectWEvents::CConnectionPoint::~CConnectionPoint ()
{
    int x;

    // clean up some memory stuff
    //
    if (!m_cSinks)
        return;
    else if (m_cSinks == 1)
        ((IUnknown *)m_rgSinks)->Release();
    else {
        for (x = 0; x < m_cSinks; x++)
            QUICK_RELEASE(m_rgSinks[x]);
        HeapFree(g_hHeap, 0, m_rgSinks);
    }
}

//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPiont::DoInvoke
//=--------------------------------------------------------------------------=
// fires an event to all listening on our event interface.
//
// Parameters:
//    DISPID            - [in] event to fire.
//    DISPPARAMS        - [in]
//
// Notes:
//
void CAutomationObjectWEvents::CConnectionPoint::DoInvoke
(
    DISPID      dispid,
    DISPPARAMS *pdispparams
)
{
    int iConnection;

    // if we don't have any sinks, then there's nothing to do.  we intentionally
    // ignore errors here.
    //
    if (m_cSinks == 0)
        return;
    else if (m_cSinks == 1)
        ((IDispatch *)m_rgSinks)->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
    else
        for (iConnection = 0; iConnection < m_cSinks; iConnection++)
            ((IDispatch *)m_rgSinks[iConnection])->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, pdispparams, NULL, NULL, NULL);
}

//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::DoOnChanged
//=--------------------------------------------------------------------------=
// fires the OnChanged event for IPropertyNotifySink listeners.
//
// Parameters:
//    DISPID            - [in] dude that changed.
//
// Output:
//    none
//
// Notes:
//
void CAutomationObjectWEvents::CConnectionPoint::DoOnChanged
(
    DISPID dispid
)
{
    int iConnection;

    // if we don't have any sinks, then there's nothing to do.
    //
    if (m_cSinks == 0)
        return;
    else if (m_cSinks == 1)
        ((IPropertyNotifySink *)m_rgSinks)->OnChanged(dispid);
    else
        for (iConnection = 0; iConnection < m_cSinks; iConnection++)
            ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnChanged(dispid);
}

//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::CConnectionPoint::DoOnRequestEdit
//=--------------------------------------------------------------------------=
// fires the OnRequestEdit for IPropertyNotifySinkListeners
//
// Parameters:
//    DISPID             - [in] dispid user wants to change.
//
// Output:
//    BOOL               - false means you cant
//
// Notes:
//
BOOL CAutomationObjectWEvents::CConnectionPoint::DoOnRequestEdit
(
    DISPID dispid
)
{
    HRESULT hr;
    int     iConnection;

    // if we don't have any sinks, then there's nothing to do.
    //
    if (m_cSinks == 0)
        hr = S_OK;
    else if (m_cSinks == 1)
        hr =((IPropertyNotifySink *)m_rgSinks)->OnRequestEdit(dispid);
    else {
        for (iConnection = 0; iConnection < m_cSinks; iConnection++) {
            hr = ((IPropertyNotifySink *)m_rgSinks[iConnection])->OnRequestEdit(dispid);
            if (hr != S_OK) break;
        }
    }

    return (hr == S_OK) ? TRUE : FALSE;
}


//=--------------------------------------------------------------------------=
// CAutomationObjectWEvents::FireEvent
//=--------------------------------------------------------------------------=
// fires an event.  handles arbitrary number of arguments.
//
// Parameters:
//    EVENTINFO *        - [in] struct that describes the event.
//    ...                - arguments to the event
//
// Output:
//    none
//
// Notes:
//    - use stdarg's va_* macros.
//
void __cdecl CAutomationObjectWEvents::FireEvent
(
    EVENTINFO *pEventInfo,
    ...
)
{
    va_list    valist;
    DISPPARAMS dispparams;
    VARIANT    rgvParameters[MAX_ARGS];
    VARIANT   *pv;
    VARTYPE    vt;
    int        iParameter;
    int        cbSize;

    ASSERT(pEventInfo->cParameters <= MAX_ARGS, L"Don't support more than MAX_ARGS params.  sorry.");

    va_start(valist, pEventInfo);

    // copy the Parameters into the rgvParameters array.  make sure we reverse
    // them for automation
    //
    pv = &(rgvParameters[pEventInfo->cParameters - 1]);
    for (iParameter = 0; iParameter < pEventInfo->cParameters; iParameter++) {

        vt = pEventInfo->rgTypes[iParameter];

        // if it's a by value variant, then just copy the whole
        // dang thing
        //
        if (vt == VT_VARIANT)
            *pv = va_arg(valist, VARIANT);
        else {
            // copy the vt and the data value.
            //
            pv->vt = vt;
            if (vt & VT_BYREF)
                cbSize = sizeof(void *);
            else
                cbSize = g_rgcbDataTypeSize[vt];

            // small optimization -- we can copy 2/4 bytes over quite
            // quickly.
            //
            if (cbSize == sizeof(short))
                V_I2(pv) = va_arg(valist, short);
            else if (cbSize == 4)
                V_I4(pv) = va_arg(valist, long);
            else {
                // copy over 8 bytes
                //
                ASSERT(cbSize == 8, L"don't recognize the type!!");
                V_CY(pv) = va_arg(valist, CURRENCY);
            }
        }

        pv--;
    }

    // fire the event
    //
    dispparams.rgvarg = rgvParameters;
    dispparams.cArgs = pEventInfo->cParameters;
    dispparams.rgdispidNamedArgs = NULL;
    dispparams.cNamedArgs = 0;

    m_cpEvents.DoInvoke(pEventInfo->dispid, &dispparams);

    va_end(valist);
}

//=--------------------------------------------------------------------------=
// CopyAndAddRefObject
//=--------------------------------------------------------------------------=
// copies an object pointer, and then addref's the object.
//
// Parameters:
//    void *        - [in] dest.
//    const void *  - [in] src
//    DWORD         - [in] size, ignored, since it's always 4
//
// Notes:
//
void WINAPI CopyAndAddRefObject
(
    void       *pDest,
    const void *pSource,
    DWORD       dwSize
)
{
    ASSERT(pDest && pSource, L"Bogus Pointer(s) passed into CopyAndAddRefObject!!!!");

    *((IUnknown **)pDest) = *((IUnknown **)pSource);
    ADDREF_OBJECT(*((IUnknown **)pDest));

    return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -