IOLECONT.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:12k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*
  2.  * IOLECONT.CPP
  3.  * Patron Chapter 22
  4.  *
  5.  * Implementation of the IOleItemContainer interface for Patron's
  6.  * CPage and CPatronDoc alike, using the constructor parameter fDoc
  7.  * to differentiate.
  8.  *
  9.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Microsoft
  12.  * Internet  :  kraigb@microsoft.com
  13.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  14.  */
  15. #include <stdlib.h>
  16. #include "patron.h"
  17. /*
  18.  * CImpIOleItemContainer::CImpIOleItemContainer
  19.  * CImpIOleItemContainer::~CImpIOleItemContainer
  20.  *
  21.  * Parameters (Constructor):
  22.  *  pObj            LPVOID of the page or pages.
  23.  *  pUnkOuter       LPUNKNOWN to which we delegate.
  24.  *  fDoc            BOOL indicating if we're in CPatronDoc or CPage
  25.  */
  26. CImpIOleItemContainer::CImpIOleItemContainer(LPVOID pObj
  27.     , LPUNKNOWN pUnkOuter, BOOL fDoc)
  28.     {
  29.     m_cRef=0;
  30.     m_fDoc=fDoc;
  31.     if (fDoc)
  32.         {
  33.         m_pDoc=(PCPatronDoc)pObj;
  34.         m_pPage=NULL;
  35.         }
  36.     else
  37.         {
  38.         m_pDoc=NULL;
  39.         m_pPage=(PCPage)pObj;
  40.         }
  41.     m_pUnkOuter=pUnkOuter;
  42.     return;
  43.     }
  44. CImpIOleItemContainer::~CImpIOleItemContainer(void)
  45.     {
  46.     return;
  47.     }
  48. /*
  49.  * CImpIOleItemContainer::QueryInterface
  50.  * CImpIOleItemContainer::AddRef
  51.  * CImpIOleItemContainer::Release
  52.  *
  53.  * Purpose:
  54.  *  IUnknown members for CImpIOleItemContainer object.
  55.  */
  56. STDMETHODIMP CImpIOleItemContainer::QueryInterface(REFIID riid
  57.     , PPVOID ppv)
  58.     {
  59.     return m_pUnkOuter->QueryInterface(riid, ppv);
  60.     }
  61. STDMETHODIMP_(ULONG) CImpIOleItemContainer::AddRef(void)
  62.     {
  63.     ++m_cRef;
  64.     return m_pUnkOuter->AddRef();
  65.     }
  66. STDMETHODIMP_(ULONG) CImpIOleItemContainer::Release(void)
  67.     {
  68.     --m_cRef;
  69.     return m_pUnkOuter->Release();
  70.     }
  71. /*
  72.  * CImpIOleItemContainer::ParseDisplayName
  73.  *
  74.  * Purpose:
  75.  *  Inherited member of IParseDisplayName that takes a string name
  76.  *  and turns out a moniker for it.
  77.  *
  78.  * Parameters:
  79.  *  pbc             LPBC to the binding context
  80.  *  pszName         LPOLESTR to the name to parse.
  81.  *  pchEaten        ULONG * into which to store how many
  82.  *                  characters we scanned in the display name.
  83.  *  ppmk            LPMONIKER * in which to return the moniker.
  84.  *
  85.  * Return Value:
  86.  *  HRESULT         NOERROR or a general error value.
  87.  */
  88. STDMETHODIMP CImpIOleItemContainer::ParseDisplayName(LPBC pbc
  89.     , LPOLESTR pszName, ULONG *pchEaten, LPMONIKER *ppmk)
  90.     {
  91.     OLECHAR     ch;
  92.     ULONG       chEaten=0;
  93.     TCHAR       szName[256];
  94.     TCHAR       szComp[15];
  95.     LPTSTR      psz;
  96.     UINT        cch;
  97.     *ppmk=NULL;
  98.     *pchEaten=0;
  99.     /*
  100.      * All we have to look for is the string between the !
  101.      * delimeters (or a null terminator).  pszName should be pointing
  102.      * to a !, so skip it and scan the string for a ! or 0,
  103.      * then pass the result to CreateItemMoniker.
  104.      */
  105.     psz=szName;
  106.     ch=*pszName++;
  107.     chEaten++;
  108.     if ((OLECHAR)'!'!=ch)
  109.         return ResultFromScode(MK_E_SYNTAX);
  110.     ch=*pszName++;
  111.     while ((OLECHAR)0!=ch && (OLECHAR)'!' !=ch)
  112.         {
  113.         *psz++=(TCHAR)ch;
  114.         chEaten++;
  115.         ch=*pszName++;
  116.         }
  117.     *psz=(TCHAR)0;
  118.     /*
  119.      * Syntax check.  If we're the DOcument object, check for
  120.      * "Page n" at the beginning of the string.  Otherwise check
  121.      * for "Tenant n".
  122.      */
  123.     lstrcpy(szComp, m_fDoc ? TEXT("Page ") : TEXT("Tenant "));
  124.     //Does szName start with szComp?
  125.     cch=lstrlen(szComp);
  126.     if (0!=_tcsncicmp(szName, szComp, cch))
  127.         {
  128.         *pchEaten=1;    //Parsed ! at least
  129.         return ResultFromScode(MK_E_SYNTAX);
  130.         }
  131.     //Check for a number in szName
  132.     if ((TCHAR)'0' != szName[cch])
  133.         {
  134.         if (0==_ttoi(szName+cch))
  135.             {
  136.             *pchEaten=cch;  //Got past name
  137.             return ResultFromScode(MK_E_SYNTAX);
  138.             }
  139.         }
  140.     *pchEaten=chEaten;
  141.    #ifdef WIN32ANSI
  142.     //Use the ANSI version here since szName is ANSI
  143.     return INOLE_CreateItemMoniker(TEXT("!"), szName, ppmk);
  144.    #else
  145.     return CreateItemMoniker(OLETEXT("!"), szName, ppmk);
  146.    #endif
  147.     }
  148. /*
  149.  * CImpIOleItemContainer::EnumObjects
  150.  *
  151.  * Purpose:
  152.  *  Creates and returns an IEnumUnknown object that allows the
  153.  *  caller to walk through the objects in this continer thing.
  154.  *
  155.  * Parameters:
  156.  *  dwFlags         DWORD specifying what kind of objects to
  157.  *                  enumerate.
  158.  *  ppEnum          LPENUMUNKNOWN * into which to return the
  159.  *                  enumerator
  160.  *
  161.  * Return Value:
  162.  *  HRESULT         NOERROR or a general error value.
  163.  */
  164. STDMETHODIMP CImpIOleItemContainer::EnumObjects(DWORD dwFlags
  165.     , LPENUMUNKNOWN *ppEnum)
  166.     {
  167.     *ppEnum=NULL;
  168.     return ResultFromScode(E_NOTIMPL);
  169.     }
  170. /*
  171.  * CImpIOleItemContainer::LockContainer
  172.  *
  173.  * Purpose:
  174.  *  Establishes a lock on the container to prevent it from shutting
  175.  *  down outside of user control.  This is used to control the
  176.  *  lifetime of the container when it's used to update a link to an
  177.  *  embedded object within it.  If we're unlock and the user has not
  178.  *  taken control, we close.
  179.  *
  180.  * Parameters:
  181.  *  fLock           BOOL indicating a lock or unlock.
  182.  *
  183.  * Return Value:
  184.  *  HRESULT         NOERROR or a general error value.
  185.  */
  186. STDMETHODIMP CImpIOleItemContainer::LockContainer(BOOL fLock)
  187.     {
  188.     /*
  189.      * This is pretty much the same implementation as
  190.      * IClassFactory::LockServer, and we can use the same lock
  191.      * count to accomplish our goal.
  192.      */
  193.     if (fLock)
  194.         g_cLock++;
  195.     else
  196.         {
  197.         g_cLock--;
  198.         g_cObj++;
  199.         ObjectDestroyed();
  200.         }
  201.     return NOERROR;
  202.     }
  203. /*
  204.  * CImpIOleItemContainer::GetObject
  205.  *
  206.  * Purpose:
  207.  *  Returns the requested interface pointer on an object in this
  208.  *  container.
  209.  *
  210.  * Parameters:
  211.  *  pszItem         LPOLESTR to the item we must locate.
  212.  *  dwSpeed         DWORD identifying how long the caller is willing
  213.  *                  to wait.
  214.  *  pcb             LPBINDCTX providing the binding context.
  215.  *  riid            REFIID of the interface requested.
  216.  *  ppv             PPVOID into which to return the object.
  217.  *
  218.  * Return Value:
  219.  *  HRESULT         NOERROR or a general error value.
  220.  */
  221. STDMETHODIMP CImpIOleItemContainer::GetObject(LPOLESTR pszItem
  222.     , DWORD dwSpeed, LPBINDCTX pbc, REFIID riid, PPVOID ppv)
  223.     {
  224.     DWORD       dw;
  225.     char        szTemp[40];     //ANSI for atol
  226.     HRESULT     hr=ResultFromScode(E_FAIL);
  227.     PCPage      pPage;
  228.     PCTenant    pTenant;
  229.     LPUNKNOWN   pObj;
  230.     UINT        i, iCur;
  231.     *ppv=NULL;
  232.     if (m_fDoc)
  233.         {
  234.         /*
  235.          * The item name should be "Page n", so we'll do it the
  236.          * easy way:  call atol on pszItem+5 (we always know that
  237.          * we'll have "Page " there since we put it there (see
  238.          * CPage::GetStorageName).
  239.          */
  240.         UNICODETOANSI((pszItem+5), szTemp, sizeof(szTemp));
  241.         dw=atol(szTemp);
  242.         i=m_pDoc->m_pPG->IPageGetFromID(dw, &pPage, FALSE);
  243.         if (NOVALUE==i)
  244.             return hr;
  245.         /*
  246.          * If we're asked for immediate speed, only do this if the
  247.          * page is already current, i.e. everything is loaded.
  248.          */
  249.         iCur=m_pDoc->m_pPG->CurPageGet();
  250.         if (BINDSPEED_IMMEDIATE==dwSpeed && iCur!=i)
  251.             return ResultFromScode(MK_E_EXCEEDEDDEADLINE);
  252.         m_pDoc->m_pPG->CurPageSet(i);
  253.         //This will have changed to be the current page now.
  254.         if (NULL!=m_pDoc->m_pPG->m_pPageCur)
  255.             hr=m_pDoc->m_pPG->m_pPageCur->QueryInterface(riid, ppv);
  256.         }
  257.     else
  258.         {
  259.         if (TenantFromName(pszItem, &pTenant))
  260.             {
  261.             pTenant->ObjectGet(&pObj);
  262.             /*
  263.              * If we're asked for immediate or moderate, only work
  264.              * if the object is already running.
  265.              */
  266.             hr=IsRunning(pszItem);  //This is the function below
  267.             if ((BINDSPEED_IMMEDIATE==dwSpeed
  268.                 || BINDSPEED_MODERATE==dwSpeed) && NOERROR!=hr)
  269.                 hr=ResultFromScode(MK_E_EXCEEDEDDEADLINE);
  270.             else
  271.                 {
  272.                 //IMPORTANT:  Make sure this object is running first
  273.                 OleRun(pObj);
  274.                 hr=pObj->QueryInterface(riid, ppv);
  275.                 }
  276.             pObj->Release();
  277.             }
  278.         else
  279.             hr=ResultFromScode(MK_E_NOOBJECT);
  280.         }
  281.     return hr;
  282.     }
  283. /*
  284.  * CImpIOleItemContainer::GetObjectStorage
  285.  *
  286.  * Purpose:
  287.  *  Similar to get Object in that we have to locate the object
  288.  *  described by a given name, but instead of returning any old
  289.  *  interface we return a storage element.
  290.  *
  291.  * Parameters:
  292.  *  pszItem         LPOLESTR to the item we must locate.
  293.  *  pcb             LPBINDCTX providing the binding context.
  294.  *  riid            REFIID of the interface requested.  Usually
  295.  *                  IStorage or IStream.
  296.  *  ppv             PPVOID into which to return the object.
  297.  *
  298.  * Return Value:
  299.  *  HRESULT         NOERROR or a general error value.
  300.  */
  301. STDMETHODIMP CImpIOleItemContainer::GetObjectStorage(LPOLESTR pszItem
  302.     , LPBINDCTX pbc, REFIID riid, PPVOID ppv)
  303.     {
  304.     PCTenant    pTenant;
  305.     *ppv=NULL;
  306.     if (m_fDoc)
  307.         return ResultFromScode(E_NOTIMPL);
  308.     //Can only handle IStorage.
  309.     if (IID_IStorage!=riid)
  310.         return ResultFromScode(E_NOINTERFACE);
  311.     if (TenantFromName(pszItem, &pTenant))
  312.         pTenant->StorageGet((LPSTORAGE *)ppv);
  313.     return (NULL!=*ppv) ? NOERROR : ResultFromScode(E_FAIL);
  314.     }
  315. /*
  316.  * CImpIOleItemContainer::IsRunning
  317.  *
  318.  * Purpose:
  319.  *  Answers if the object under the given name is currently running.
  320.  *
  321.  * Parameters:
  322.  *  pszItem         LPOLESTR of the item to check
  323.  *
  324.  * Return Value:
  325.  *  HRESULT         NOERROR if the object is running, S_FALSE
  326.  *                  otherwise.  Possibly MK_E_NOOBJECT if the name
  327.  *                  is bogus.
  328.  */
  329. STDMETHODIMP CImpIOleItemContainer::IsRunning(LPOLESTR pszItem)
  330.     {
  331.     HRESULT     hr;
  332.     PCTenant    pTenant;
  333.     LPUNKNOWN   pObj;
  334.     LPOLEOBJECT pIOleObject;
  335.     /*
  336.      * If this is the document's container interface, the object
  337.      * is a page and the page is always running.
  338.      */
  339.     if (m_fDoc)
  340.         return NOERROR;
  341.     else
  342.         {
  343.         if (TenantFromName(pszItem, &pTenant))
  344.             {
  345.             //Ask the actual object if its running.
  346.             pTenant->ObjectGet(&pObj);
  347.             hr=pObj->QueryInterface(IID_IOleObject
  348.                 , (PPVOID)&pIOleObject);
  349.             pObj->Release();
  350.             if (SUCCEEDED(hr))
  351.                 {
  352.                 hr=(OleIsRunning(pIOleObject))
  353.                     ? NOERROR : ResultFromScode(S_FALSE);
  354.                 pIOleObject->Release();
  355.                 }
  356.             }
  357.         else
  358.             hr=ResultFromScode(MK_E_NOOBJECT);
  359.         }
  360.     return hr;
  361.     }
  362. /*
  363.  * CImpIOleItemContainer::TenantFromName
  364.  * (Private)
  365.  *
  366.  * Purpose:
  367.  *  This function which is NOT part of the interface retrieves
  368.  *  a tenant pointer from a tenant name.
  369.  *
  370.  * Parameters:
  371.  *  pszItem         LPOLESTR of the tenant to locate.
  372.  *  ppTenant        PCTenant * in which to return the pointer.
  373.  *
  374.  * Return Value:
  375.  *  BOOL            TRUE if successful, FALSE otherwise.
  376.  */
  377. BOOL CImpIOleItemContainer::TenantFromName(LPOLESTR pszItem
  378.     , PCTenant *ppTenant)
  379.     {
  380.     DWORD       dw;
  381.     char        szTemp[40];     //ANSI for atol
  382.     if (m_fDoc)
  383.         return FALSE;
  384.     //The item name should be "Tenant xxxx", so use pszItem+7.
  385.     UNICODETOANSI((pszItem+7), szTemp, sizeof(szTemp));
  386.     dw=atol(szTemp);
  387.     *ppTenant=NULL;
  388.     return m_pPage->TenantGetFromID(dw, ppTenant, FALSE);
  389.     }