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

📄 iolecont.cpp

📁 英文版的 想要的话可以下载了 为大家服务
💻 CPP
字号:
/*
 * IOLECONT.CPP
 * Patron Chapter 22
 *
 * Implementation of the IOleItemContainer interface for Patron's
 * CPage and CPatronDoc alike, using the constructor parameter fDoc
 * to differentiate.
 *
 * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
 *
 * Kraig Brockschmidt, Microsoft
 * Internet  :  kraigb@microsoft.com
 * Compuserve:  >INTERNET:kraigb@microsoft.com
 */


#include <stdlib.h>
#include "patron.h"


/*
 * CImpIOleItemContainer::CImpIOleItemContainer
 * CImpIOleItemContainer::~CImpIOleItemContainer
 *
 * Parameters (Constructor):
 *  pObj            LPVOID of the page or pages.
 *  pUnkOuter       LPUNKNOWN to which we delegate.
 *  fDoc            BOOL indicating if we're in CPatronDoc or CPage
 */

CImpIOleItemContainer::CImpIOleItemContainer(LPVOID pObj
    , LPUNKNOWN pUnkOuter, BOOL fDoc)
    {
    m_cRef=0;
    m_fDoc=fDoc;

    if (fDoc)
        {
        m_pDoc=(PCPatronDoc)pObj;
        m_pPage=NULL;
        }
    else
        {
        m_pDoc=NULL;
        m_pPage=(PCPage)pObj;
        }

    m_pUnkOuter=pUnkOuter;
    return;
    }

CImpIOleItemContainer::~CImpIOleItemContainer(void)
    {
    return;
    }




/*
 * CImpIOleItemContainer::QueryInterface
 * CImpIOleItemContainer::AddRef
 * CImpIOleItemContainer::Release
 *
 * Purpose:
 *  IUnknown members for CImpIOleItemContainer object.
 */

STDMETHODIMP CImpIOleItemContainer::QueryInterface(REFIID riid
    , PPVOID ppv)
    {
    return m_pUnkOuter->QueryInterface(riid, ppv);
    }


STDMETHODIMP_(ULONG) CImpIOleItemContainer::AddRef(void)
    {
    ++m_cRef;
    return m_pUnkOuter->AddRef();
    }

STDMETHODIMP_(ULONG) CImpIOleItemContainer::Release(void)
    {
    --m_cRef;
    return m_pUnkOuter->Release();
    }



/*
 * CImpIOleItemContainer::ParseDisplayName
 *
 * Purpose:
 *  Inherited member of IParseDisplayName that takes a string name
 *  and turns out a moniker for it.
 *
 * Parameters:
 *  pbc             LPBC to the binding context
 *  pszName         LPOLESTR to the name to parse.
 *  pchEaten        ULONG * into which to store how many
 *                  characters we scanned in the display name.
 *  ppmk            LPMONIKER * in which to return the moniker.
 *
 * Return Value:
 *  HRESULT         NOERROR or a general error value.
 */

STDMETHODIMP CImpIOleItemContainer::ParseDisplayName(LPBC pbc
    , LPOLESTR pszName, ULONG *pchEaten, LPMONIKER *ppmk)
    {
    OLECHAR     ch;
    ULONG       chEaten=0;
    TCHAR       szName[256];
    TCHAR       szComp[15];
    LPTSTR      psz;
    UINT        cch;

    *ppmk=NULL;
    *pchEaten=0;

    /*
     * All we have to look for is the string between the !
     * delimeters (or a null terminator).  pszName should be pointing
     * to a !, so skip it and scan the string for a ! or 0,
     * then pass the result to CreateItemMoniker.
     */

    psz=szName;

    ch=*pszName++;
    chEaten++;

    if ((OLECHAR)'!'!=ch)
        return ResultFromScode(MK_E_SYNTAX);

    ch=*pszName++;

    while ((OLECHAR)0!=ch && (OLECHAR)'!' !=ch)
        {
        *psz++=(TCHAR)ch;
        chEaten++;
        ch=*pszName++;
        }

    *psz=(TCHAR)0;

    /*
     * Syntax check.  If we're the DOcument object, check for
     * "Page n" at the beginning of the string.  Otherwise check
     * for "Tenant n".
     */
    lstrcpy(szComp, m_fDoc ? TEXT("Page ") : TEXT("Tenant "));

    //Does szName start with szComp?
    cch=lstrlen(szComp);

    if (0!=_tcsncicmp(szName, szComp, cch))
        {
        *pchEaten=1;    //Parsed ! at least
        return ResultFromScode(MK_E_SYNTAX);
        }

    //Check for a number in szName
    if ((TCHAR)'0' != szName[cch])
        {
        if (0==_ttoi(szName+cch))
            {
            *pchEaten=cch;  //Got past name
            return ResultFromScode(MK_E_SYNTAX);
            }
        }

    *pchEaten=chEaten;
   #ifdef WIN32ANSI
    //Use the ANSI version here since szName is ANSI
    return INOLE_CreateItemMoniker(TEXT("!"), szName, ppmk);
   #else
    return CreateItemMoniker(OLETEXT("!"), szName, ppmk);
   #endif
    }




/*
 * CImpIOleItemContainer::EnumObjects
 *
 * Purpose:
 *  Creates and returns an IEnumUnknown object that allows the
 *  caller to walk through the objects in this continer thing.
 *
 * Parameters:
 *  dwFlags         DWORD specifying what kind of objects to
 *                  enumerate.
 *  ppEnum          LPENUMUNKNOWN * into which to return the
 *                  enumerator
 *
 * Return Value:
 *  HRESULT         NOERROR or a general error value.
 */

STDMETHODIMP CImpIOleItemContainer::EnumObjects(DWORD dwFlags
    , LPENUMUNKNOWN *ppEnum)
    {
    *ppEnum=NULL;
    return ResultFromScode(E_NOTIMPL);
    }




/*
 * CImpIOleItemContainer::LockContainer
 *
 * Purpose:
 *  Establishes a lock on the container to prevent it from shutting
 *  down outside of user control.  This is used to control the
 *  lifetime of the container when it's used to update a link to an
 *  embedded object within it.  If we're unlock and the user has not
 *  taken control, we close.
 *
 * Parameters:
 *  fLock           BOOL indicating a lock or unlock.
 *
 * Return Value:
 *  HRESULT         NOERROR or a general error value.
 */

STDMETHODIMP CImpIOleItemContainer::LockContainer(BOOL fLock)
    {
    /*
     * This is pretty much the same implementation as
     * IClassFactory::LockServer, and we can use the same lock
     * count to accomplish our goal.
     */

    if (fLock)
        g_cLock++;
    else
        {
        g_cLock--;
        g_cObj++;
        ObjectDestroyed();
        }

    return NOERROR;
    }






/*
 * CImpIOleItemContainer::GetObject
 *
 * Purpose:
 *  Returns the requested interface pointer on an object in this
 *  container.
 *
 * Parameters:
 *  pszItem         LPOLESTR to the item we must locate.
 *  dwSpeed         DWORD identifying how long the caller is willing
 *                  to wait.
 *  pcb             LPBINDCTX providing the binding context.
 *  riid            REFIID of the interface requested.
 *  ppv             PPVOID into which to return the object.
 *
 * Return Value:
 *  HRESULT         NOERROR or a general error value.
 */

STDMETHODIMP CImpIOleItemContainer::GetObject(LPOLESTR pszItem
    , DWORD dwSpeed, LPBINDCTX pbc, REFIID riid, PPVOID ppv)
    {
    DWORD       dw;
    char        szTemp[40];     //ANSI for atol
    HRESULT     hr=ResultFromScode(E_FAIL);
    PCPage      pPage;
    PCTenant    pTenant;
    LPUNKNOWN   pObj;
    UINT        i, iCur;

    *ppv=NULL;

    if (m_fDoc)
        {
        /*
         * The item name should be "Page n", so we'll do it the
         * easy way:  call atol on pszItem+5 (we always know that
         * we'll have "Page " there since we put it there (see
         * CPage::GetStorageName).
         */

        UNICODETOANSI((pszItem+5), szTemp, sizeof(szTemp));
        dw=atol(szTemp);

        i=m_pDoc->m_pPG->IPageGetFromID(dw, &pPage, FALSE);

        if (NOVALUE==i)
            return hr;

        /*
         * If we're asked for immediate speed, only do this if the
         * page is already current, i.e. everything is loaded.
         */
        iCur=m_pDoc->m_pPG->CurPageGet();

        if (BINDSPEED_IMMEDIATE==dwSpeed && iCur!=i)
            return ResultFromScode(MK_E_EXCEEDEDDEADLINE);

        m_pDoc->m_pPG->CurPageSet(i);

        //This will have changed to be the current page now.
        if (NULL!=m_pDoc->m_pPG->m_pPageCur)
            hr=m_pDoc->m_pPG->m_pPageCur->QueryInterface(riid, ppv);
        }
    else
        {
        if (TenantFromName(pszItem, &pTenant))
            {
            pTenant->ObjectGet(&pObj);

            /*
             * If we're asked for immediate or moderate, only work
             * if the object is already running.
             */
            hr=IsRunning(pszItem);  //This is the function below

            if ((BINDSPEED_IMMEDIATE==dwSpeed
                || BINDSPEED_MODERATE==dwSpeed) && NOERROR!=hr)
                hr=ResultFromScode(MK_E_EXCEEDEDDEADLINE);
            else
                {
                //IMPORTANT:  Make sure this object is running first
                OleRun(pObj);
                hr=pObj->QueryInterface(riid, ppv);
                }

            pObj->Release();
            }
        else
            hr=ResultFromScode(MK_E_NOOBJECT);
        }

    return hr;
    }






/*
 * CImpIOleItemContainer::GetObjectStorage
 *
 * Purpose:
 *  Similar to get Object in that we have to locate the object
 *  described by a given name, but instead of returning any old
 *  interface we return a storage element.
 *
 * Parameters:
 *  pszItem         LPOLESTR to the item we must locate.
 *  pcb             LPBINDCTX providing the binding context.
 *  riid            REFIID of the interface requested.  Usually
 *                  IStorage or IStream.
 *  ppv             PPVOID into which to return the object.
 *
 * Return Value:
 *  HRESULT         NOERROR or a general error value.
 */

STDMETHODIMP CImpIOleItemContainer::GetObjectStorage(LPOLESTR pszItem
    , LPBINDCTX pbc, REFIID riid, PPVOID ppv)
    {
    PCTenant    pTenant;

    *ppv=NULL;

    if (m_fDoc)
        return ResultFromScode(E_NOTIMPL);

    //Can only handle IStorage.
    if (IID_IStorage!=riid)
        return ResultFromScode(E_NOINTERFACE);

    if (TenantFromName(pszItem, &pTenant))
        pTenant->StorageGet((LPSTORAGE *)ppv);

    return (NULL!=*ppv) ? NOERROR : ResultFromScode(E_FAIL);
    }






/*
 * CImpIOleItemContainer::IsRunning
 *
 * Purpose:
 *  Answers if the object under the given name is currently running.
 *
 * Parameters:
 *  pszItem         LPOLESTR of the item to check
 *
 * Return Value:
 *  HRESULT         NOERROR if the object is running, S_FALSE
 *                  otherwise.  Possibly MK_E_NOOBJECT if the name
 *                  is bogus.
 */

STDMETHODIMP CImpIOleItemContainer::IsRunning(LPOLESTR pszItem)
    {
    HRESULT     hr;
    PCTenant    pTenant;
    LPUNKNOWN   pObj;
    LPOLEOBJECT pIOleObject;

    /*
     * If this is the document's container interface, the object
     * is a page and the page is always running.
     */
    if (m_fDoc)
        return NOERROR;
    else
        {
        if (TenantFromName(pszItem, &pTenant))
            {
            //Ask the actual object if its running.
            pTenant->ObjectGet(&pObj);
            hr=pObj->QueryInterface(IID_IOleObject
                , (PPVOID)&pIOleObject);
            pObj->Release();

            if (SUCCEEDED(hr))
                {
                hr=(OleIsRunning(pIOleObject))
                    ? NOERROR : ResultFromScode(S_FALSE);
                pIOleObject->Release();
                }
            }
        else
            hr=ResultFromScode(MK_E_NOOBJECT);
        }

    return hr;
    }




/*
 * CImpIOleItemContainer::TenantFromName
 * (Private)
 *
 * Purpose:
 *  This function which is NOT part of the interface retrieves
 *  a tenant pointer from a tenant name.
 *
 * Parameters:
 *  pszItem         LPOLESTR of the tenant to locate.
 *  ppTenant        PCTenant * in which to return the pointer.
 *
 * Return Value:
 *  BOOL            TRUE if successful, FALSE otherwise.
 */

BOOL CImpIOleItemContainer::TenantFromName(LPOLESTR pszItem
    , PCTenant *ppTenant)
    {
    DWORD       dw;
    char        szTemp[40];     //ANSI for atol

    if (m_fDoc)
        return FALSE;

    //The item name should be "Tenant xxxx", so use pszItem+7.
    UNICODETOANSI((pszItem+7), szTemp, sizeof(szTemp));
    dw=atol(szTemp);

    *ppTenant=NULL;

    return m_pPage->TenantGetFromID(dw, ppTenant, FALSE);
    }

⌨️ 快捷键说明

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