🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.cppbuilder.internet.web
Article #1239

Re: IOleClientSite implementation (subclass)

#1239
From: Remy Lebeau (TeamB)
Date: Tue, 29 Mar 2005 20:20
283 lines
8642 bytes
"SD" <nospawm@please.it> wrote in message
news:424983a3@newsgroups.borland.com...

> __fastcall TForm1::~TForm1()
> {
>   // frees objects
>   delete FCppWebBrowserWrapper;
> }

Don't use delete here.  Interfaces are reference counted.  The browser is
probably still holding on to the interface, so call the object's Release()
method instead.  When the browser is done with the interface, it will call
Release() as well.  When the reference count falls to 0, the interface
should delete itself only at that time.

>   IOleClientSite *FIOleClientSite;
<snip>
>   ~QCppWebBrowserWrapper()
>   {
>     IOleObject* OleObject = NULL;
>     ((IDispatch *) FWebBrowser->OleObject)->QueryInterface(IID_IOleObject,
> (void **) &OleObject);
>     OleObject->SetClientSite(FIOleClientSite);
>   }

You don't need to do any of that.  You are solely responsible for providing
the IOleClientSite to the browser, so you will only have 1 IOleClientSite
available.  There is nothing to give back to the browser when your
IOleClientSite is being destroyed.

>   virtual void STDMETHODCALLTYPE Initialize(TCppWebBrowser *WebBrowser)
>   {
>     FWebBrowser = WebBrowser;
>     IOleObject* OleObject = NULL;
>     ((IDispatch *) FWebBrowser->OleObject)->QueryInterface(IID_IOleObject,
> (void **) &OleObject);
>     OleObject->GetClientSite(&FIOleClientSite);
>     OleObject->SetClientSite((IOleClientSite *) this);
>   }

You are not calling Release() on the OleObject.  You are also not validating
that the OleObject is even a valid object before accessing it.  You should
be querying the IOleObject from the browser's ControlInterface anyway, not
its OleObject property.

>   virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID classid, void**
> intf)
>   {
> //      return FIOleClientSite->QueryInterface(classid, intf);
>     if (classid == IID_IDocHostUIHandler)
>     {
>       *intf = (IDocHostUIHandler *) this;
>       return S_OK;
>     }
>     else
>       return FIOleClientSite->QueryInterface(classid, intf);
>   }

Since you should not be holding on to the browser's IOleClientSite to begin
with, that implementation is completely wrong.

>   virtual ULONG STDMETHODCALLTYPE AddRef()
>   {
> //    return FIOleClientSite->AddRef();
> //    InterlockedIncrement(&FRefCount);
>     return FRefCount;
>   }

You are never incrementing the reference count at all.

>   virtual ULONG STDMETHODCALLTYPE Release()
>   {
> //    return FIOleClientSite->Release();
> //    InterlockedDecrement(&FRefCount);
>     if (FRefCount == 0)
>       delete this;
>     return FRefCount;
>   }

You are never decrementing the reference count at all.  Not only that, but
if the reference count ever did get decremented to 0, your code would crash
because you would be returning to return FRefCount via an invalid 'this'
pointer.

With all of that said, try this code:


    class QCppWebBrowserWrapper :
        public IOleClientSite,
        public IDocHostUIHandler
    {
    private:
        ULONG FRefCount;
        TCppWebBrowser *FWebBrowser;

    public:
        QCppWebBrowserWrapper(TCppWebBrowser *WebBrowser)
            : FRefCount(1), FWebBrowser(WebBrowser)
        {
            if( (FWebBrowser) && (FWebBrowser->ControlInterface) )
            {
                IOleObject *pObj = NULL;
                if(
SUCCEEDED(FWebBrowser->ControlInterface->QueryInterface(IID_IOleObject,
(void **) &pObj)) )
                {
                    pObj->SetClientSite(this);
                    pObj->Release();
                }
            }
        }

        virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void**
intf)
        {
            if( intf == NULL )
                return E_POINTER;

            *intf = NULL;

            if( riid == IID_IUnknown )
                // workaround for a compiler error
                *intf = (IUnknown*) ((IDocHostUIHandler*) this);

            else if( riid == IID_IOleClientSite )
                *intf = (IOleClientSite*) this;

            else if( riid == IID_IDocHostUIHandler )
                *intf = (IDocHostUIHandler*) this;

            if( *intf == NULL )
                return E_NOINTERFACE;

            AddRef();
            return S_OK;
        }

        virtual ULONG STDMETHODCALLTYPE AddRef()
        {
            return ++FRefCount;
        }

        virtual ULONG STDMETHODCALLTYPE Release()
        {
            if( --FRefCount == 0 )
            {
                delete this;
                return 0;
            }
            return FRefCount;
        }

        virtual HRESULT STDMETHODCALLTYPE SaveObject(void)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE GetMoniker(DWORD, DWORD,
IMoniker**)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE GetContainer(IOleContainer **)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE ShowObject(void)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE OnShowWindow(BOOL)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE RequestNewObjectLayout(void)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE ShowContextMenu(DWORD, POINT*,
IUnknown*, IDispatch*)
        {
            return S_OK;
        }

        virtual HRESULT STDMETHODCALLTYPE GetHostInfo(DOCHOSTUIINFO*)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE ShowUI(DWORD,
IOleInPlaceActiveObject*, IOleCommandTarget*, IOleInPlaceFrame*,
IOleInPlaceUIWindow*)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE HideUI(void)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE UpdateUI(void)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate(BOOL)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate(BOOL)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE ResizeBorder(LPCRECT,
IOleInPlaceUIWindow*, BOOL)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(LPMSG, const
GUID*, DWORD)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE GetOptionKeyPath(LPOLESTR*, DWORD)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE GetDropTarget(IDropTarget*,
IDropTarget**)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE GetExternal(IDispatch**)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE TranslateUrl(DWORD, OLECHAR*,
OLECHAR**)
        {
            return E_NOTIMPL;
        }

        virtual HRESULT STDMETHODCALLTYPE FilterDataObject(IDataObject*,
IDataObject**)
        {
            return E_NOTIMPL;
        }
    };


    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
        FWrapper = new QCppWebBrowserWrapper(CppWebBrowser1);
    }

    __fastcall TForm1::~TForm1()
    {
        if( FWrapper )
            FWrapper->Release();
    }


Gambit
Technical Details
Message-ID: <4249b838$1@newsgroups.borland.com>
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!newsread.com!newsprint.newsread.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail
References: <424983a3@newsgroups.borland.com>

Show Full Headers
Complete Article Headers
X-Google-Thread: feeec,9599a9d64bd580a8
X-Google-Attributes: gidfeeec,public
X-Google-Language: ENGLISH,ASCII-7-bit
From: "Remy Lebeau \(TeamB\)" <no.spam@no.spam.com>
Newsgroups: borland.public.cppbuilder.internet.web
References: <424983a3@newsgroups.borland.com>
Subject: Re: IOleClientSite implementation (subclass)
Date: Tue, 29 Mar 2005 12:20:27 -0800
Lines: 285
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1409
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1409
NNTP-Posting-Host: 68.69.17.41
Message-ID: <4249b838$1@newsgroups.borland.com>
X-Trace: newsgroups.borland.com 1112127544 68.69.17.41 (29 Mar 2005 12:19:04 -0800)
Path: arc1-ca.pugleaf.net!g2news1.google.com!news1.google.com!newsread.com!newsprint.newsread.com!newsfeed00.sul.t-online.de!newsfeed01.sul.t-online.de!t-online.de!newsgroups.borland.com!not-for-mail