IMessageFilterImpl

 

Chase your STA reentrancy blues away. Use IMessageFilter (with its known limitations, of course). I wrote this helper class to save some of your time :-). Its not very generic and you may need to tweak it here and there.

 


template <class T, DWORD dwTimeOut = 5000>
class ATL_NO_VTABLE IMessageFilterImpl : public IMessageFilter
{
public:
    IMessageFilterImpl()     {}
    ~IMessageFilterImpl()    { RevokeFilter(); }

public:

    HRESULT RegisterFilter() { return ::CoRegisterMessageFilter(static_cast<IMessageFilter*>(this), NULL);}
    HRESULT RevokeFilter(){ return ::CoRegisterMessageFilter(NULL, NULL); }


public: //IMessageFilter
   
    STDMETHODIMP_(DWORD) HandleInComingCall(DWORD dwCallType,HTASK threadIDCaller,DWORD dwTickCount,LPINTERFACEINFO lpInterfaceInfo)
    {
        //we CANNOT reject these calls
        if(dwCallType == CALLTYPE_ASYNC_CALLPENDING || dwCallType == CALLTYPE_ASYNC)
        {
            return SERVERCALL_ISHANDLED;
        }

        T* pT = static_cast<T*>(this);
        return pT->ProcessInComingCall(dwCallType,threadIDCaller,dwTickCount,lpInterfaceInfo);
    }

    STDMETHODIMP_(DWORD) MessagePending(HTASK threadIDCallee,DWORD dwTickCount,DWORD                                              dwPendingType)
    { return PENDINGMSG_WAITNOPROCESS; }

    STDMETHODIMP_(DWORD) RetryRejectedCall(HTASK threadIDCallee,DWORD dwTickCount,DWORD                                                  dwRejectType)
    {
        if(dwRejectType == SERVERCALL_REJECTED) { return -1; }
       
        //we must've got SERVERCALL_RETRYLATER
        return dwTimeOut;
    }

};


1. Add the IMessageFilterImpl<> to your STA object's base class list

class ATL_NO_VTABLE CFoo :
    public CComObjectRootEx<CComSingleThreadModel>,
    public IMessageFilterImpl<CFoo>, ...


2. Add the  COM_INTERFACE_ENTRY(IMessageFilter) to your COM_MAP

BEGIN_COM_MAP(CFoo)
    COM_INTERFACE_ENTRY(IFoo)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IMessageFilter) ...
END_COM_MAP()

3. Call RegisterFilter()  in the FinalConstruct()

4. Implement the following  helper as a class method:

DWORD ProcessInComingCall(DWORD dwCallType,HTASK threadIDCaller,DWORD dwTickCount,LPINTERFACEINFO lpInterfaceInfo)
{
    //Do the right thing !

    return -1; //return suitable Values !

}


This page and the source contained in(or referred to) by this page are Copyright (c) 1998, Dharma Shukla.
All rights reserved. No warrenties extended. Use at your own risk.
Do send Comments/Bugs to me :-)