IOLECONT.CPP
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:12k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * 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);
- }