home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #ifdef AFX_OLE_SEG
- #pragma code_seg(AFX_OLE_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- /////////////////////////////////////////////////////////////////////////////
- // Debug helpers
-
- #ifdef _DEBUG
- // Helper for converting IID into useful string. Only for debugging.
- LPCTSTR AFXAPI AfxGetIIDString(REFIID iid)
- {
- static TCHAR szUnfamiliar[80];
- TCHAR szByte[3];
-
- struct IID_ENTRY
- {
- const IID* piid;
- LPCTSTR lpszName;
- };
-
- #define MAKE_IID_ENTRY(name) { &name, _T(#name) }
-
- static const IID_ENTRY iidNameTable[] =
- {
- MAKE_IID_ENTRY(IID_IAdviseSink),
- MAKE_IID_ENTRY(IID_IAdviseSink2),
- MAKE_IID_ENTRY(IID_IBindCtx),
- MAKE_IID_ENTRY(IID_IClassFactory),
- MAKE_IID_ENTRY(IID_IContinueCallback),
- MAKE_IID_ENTRY(IID_IEnumOleDocumentViews),
- MAKE_IID_ENTRY(IID_IOleCommandTarget),
- MAKE_IID_ENTRY(IID_IOleDocument),
- MAKE_IID_ENTRY(IID_IOleDocumentSite),
- MAKE_IID_ENTRY(IID_IOleDocumentView),
- MAKE_IID_ENTRY(IID_IPrint),
- MAKE_IID_ENTRY(IID_IDataAdviseHolder),
- MAKE_IID_ENTRY(IID_IDataObject),
- MAKE_IID_ENTRY(IID_IDebug),
- MAKE_IID_ENTRY(IID_IDebugStream),
- MAKE_IID_ENTRY(IID_IDfReserved1),
- MAKE_IID_ENTRY(IID_IDfReserved2),
- MAKE_IID_ENTRY(IID_IDfReserved3),
- MAKE_IID_ENTRY(IID_IDispatch),
- MAKE_IID_ENTRY(IID_IDropSource),
- MAKE_IID_ENTRY(IID_IDropTarget),
- MAKE_IID_ENTRY(IID_IEnumCallback),
- MAKE_IID_ENTRY(IID_IEnumFORMATETC),
- MAKE_IID_ENTRY(IID_IEnumGeneric),
- MAKE_IID_ENTRY(IID_IEnumHolder),
- MAKE_IID_ENTRY(IID_IEnumMoniker),
- MAKE_IID_ENTRY(IID_IEnumOLEVERB),
- MAKE_IID_ENTRY(IID_IEnumSTATDATA),
- MAKE_IID_ENTRY(IID_IEnumSTATSTG),
- MAKE_IID_ENTRY(IID_IEnumString),
- MAKE_IID_ENTRY(IID_IEnumUnknown),
- MAKE_IID_ENTRY(IID_IEnumVARIANT),
- // MAKE_IID_ENTRY(IID_IExternalConnection),
- MAKE_IID_ENTRY(IID_IInternalMoniker),
- MAKE_IID_ENTRY(IID_ILockBytes),
- MAKE_IID_ENTRY(IID_IMalloc),
- MAKE_IID_ENTRY(IID_IMarshal),
- MAKE_IID_ENTRY(IID_IMessageFilter),
- MAKE_IID_ENTRY(IID_IMoniker),
- MAKE_IID_ENTRY(IID_IOleAdviseHolder),
- MAKE_IID_ENTRY(IID_IOleCache),
- MAKE_IID_ENTRY(IID_IOleCache2),
- MAKE_IID_ENTRY(IID_IOleCacheControl),
- MAKE_IID_ENTRY(IID_IOleClientSite),
- MAKE_IID_ENTRY(IID_IOleContainer),
- MAKE_IID_ENTRY(IID_IOleInPlaceActiveObject),
- MAKE_IID_ENTRY(IID_IOleInPlaceFrame),
- MAKE_IID_ENTRY(IID_IOleInPlaceObject),
- MAKE_IID_ENTRY(IID_IOleInPlaceSite),
- MAKE_IID_ENTRY(IID_IOleInPlaceUIWindow),
- MAKE_IID_ENTRY(IID_IOleItemContainer),
- MAKE_IID_ENTRY(IID_IOleLink),
- MAKE_IID_ENTRY(IID_IOleManager),
- MAKE_IID_ENTRY(IID_IOleObject),
- MAKE_IID_ENTRY(IID_IOlePresObj),
- MAKE_IID_ENTRY(IID_IOleWindow),
- MAKE_IID_ENTRY(IID_IPSFactory),
- MAKE_IID_ENTRY(IID_IParseDisplayName),
- MAKE_IID_ENTRY(IID_IPersist),
- MAKE_IID_ENTRY(IID_IPersistFile),
- MAKE_IID_ENTRY(IID_IPersistStorage),
- MAKE_IID_ENTRY(IID_IPersistStream),
- MAKE_IID_ENTRY(IID_IProxyManager),
- MAKE_IID_ENTRY(IID_IRootStorage),
- MAKE_IID_ENTRY(IID_IRpcChannel),
- MAKE_IID_ENTRY(IID_IRpcProxy),
- MAKE_IID_ENTRY(IID_IRpcStub),
- MAKE_IID_ENTRY(IID_IRunnableObject),
- MAKE_IID_ENTRY(IID_IRunningObjectTable),
- MAKE_IID_ENTRY(IID_IStdMarshalInfo),
- MAKE_IID_ENTRY(IID_IStorage),
- MAKE_IID_ENTRY(IID_IStream),
- MAKE_IID_ENTRY(IID_IStubManager),
- MAKE_IID_ENTRY(IID_IUnknown),
- MAKE_IID_ENTRY(IID_IViewObject),
- MAKE_IID_ENTRY(IID_IViewObject2),
- MAKE_IID_ENTRY(IID_NULL),
- };
- #undef MAKE_IID_ENTRY
-
- // look for it in the table
- for (int i = 0; i < _countof(iidNameTable); i++)
- {
- if (iid == *iidNameTable[i].piid)
- return iidNameTable[i].lpszName;
- }
- // if we get here, it is some IID_ we haven't heard of...
-
- wsprintf(szUnfamiliar, _T("%8.8X-%4.4X-%4.4X-"),
- iid.Data1, iid.Data2, iid.Data3);
- for (int nIndex = 0; nIndex < 8; nIndex++)
- {
- wsprintf(szByte, _T("%2.2X"), iid.Data4[nIndex]);
- lstrcat(szUnfamiliar, szByte);
- }
-
- return szUnfamiliar;
- }
- #endif
-
- /////////////////////////////////////////////////////////////////////////////
- // Component object model helpers
-
- /////////////////////////////////////////////////////////////////////////////
- // IUnknown client helpers
-
- LPUNKNOWN AFXAPI _AfxQueryInterface(LPUNKNOWN lpUnknown, REFIID iid)
- {
- ASSERT(lpUnknown != NULL);
-
- LPUNKNOWN lpW = NULL;
- if (lpUnknown->QueryInterface(iid, (LPLP)&lpW) != S_OK)
- return NULL;
-
- return lpW;
- }
-
- DWORD AFXAPI _AfxRelease(LPUNKNOWN* lplpUnknown)
- {
- ASSERT(lplpUnknown != NULL);
- if (*lplpUnknown != NULL)
- {
- DWORD dwRef = (*lplpUnknown)->Release();
- *lplpUnknown = NULL;
- return dwRef;
- }
- return 0;
- }
-
- #define GetInterfacePtr(pTarget, pEntry) \
- ((LPUNKNOWN)((BYTE*)pTarget + pEntry->nOffset))
-
- #define GetAggregatePtr(pTarget, pEntry) \
- (*(LPUNKNOWN*)((BYTE*)pTarget + pEntry->nOffset))
-
- /////////////////////////////////////////////////////////////////////////////
- // CCmdTarget interface map implementation
-
- // support for aggregation
- class CInnerUnknown : public IUnknown
- {
- public:
- STDMETHOD_(ULONG, AddRef)();
- STDMETHOD_(ULONG, Release)();
- STDMETHOD(QueryInterface)(REFIID iid, LPVOID* ppvObj);
- };
-
- // calling this function enables an object to be aggregatable
- void CCmdTarget::EnableAggregation()
- {
- // construct an CInnerUnknown just to get to the vtable
- CInnerUnknown innerUnknown;
-
- // copy the vtable & make sure initialized
- ASSERT(sizeof(m_xInnerUnknown) == sizeof(CInnerUnknown));
- m_xInnerUnknown = *(DWORD*)&innerUnknown;
- }
-
- DWORD CCmdTarget::ExternalAddRef()
- {
- // delegate to controlling unknown if aggregated
- if (m_pOuterUnknown != NULL)
- return m_pOuterUnknown->AddRef();
-
- return InternalAddRef();
- }
-
- DWORD CCmdTarget::InternalRelease()
- {
- ASSERT(GetInterfaceMap() != NULL);
-
- if (m_dwRef == 0)
- return 0;
-
- LONG lResult = InterlockedDecrement(&m_dwRef);
- if (lResult == 0)
- {
- AFX_MANAGE_STATE(m_pModuleState);
- OnFinalRelease();
- }
- return lResult;
- }
-
- DWORD CCmdTarget::ExternalRelease()
- {
- // delegate to controlling unknown if aggregated
- if (m_pOuterUnknown != NULL)
- return m_pOuterUnknown->Release();
-
- return InternalRelease();
- }
-
- // special QueryInterface used in implementation (does not AddRef)
- LPUNKNOWN CCmdTarget::GetInterface(const void* iid)
- {
- // allow general hook first chance
- LPUNKNOWN lpUnk;
- if ((lpUnk = GetInterfaceHook(iid)) != NULL)
- return lpUnk;
-
- const AFX_INTERFACEMAP* pMap = GetInterfaceMap();
- ASSERT(pMap != NULL);
- DWORD lData1 = ((IID*)iid)->Data1;
-
- // IUnknown is a special case since nobody really implements *only* it!
- BOOL bUnknown = ((DWORD*)&IID_IUnknown)[0] == lData1 &&
- ((DWORD*)iid)[1] == ((DWORD*)&IID_IUnknown)[1] &&
- ((DWORD*)iid)[2] == ((DWORD*)&IID_IUnknown)[2] &&
- ((DWORD*)iid)[3] == ((DWORD*)&IID_IUnknown)[3];
- if (bUnknown)
- {
- do
- {
- const AFX_INTERFACEMAP_ENTRY* pEntry = pMap->pEntry;
- ASSERT(pEntry != NULL);
- while (pEntry->piid != NULL)
- {
- // check INTERFACE_ENTRY macro
- LPUNKNOWN lpUnk = GetInterfacePtr(this, pEntry);
-
- // check vtable pointer (can be NULL)
- if (*(DWORD*)lpUnk != 0)
- return lpUnk;
-
- // entry did not match -- keep looking
- ++pEntry;
- }
- #ifdef _AFXDLL
- } while ((pMap = (*pMap->pfnGetBaseMap)()) != NULL);
- #else
- } while ((pMap = pMap->pBaseMap) != NULL);
- #endif
-
- // interface ID not found, fail the call
- return NULL;
- }
-
- // otherwise, walk the interface map to find the matching IID
- do
- {
- const AFX_INTERFACEMAP_ENTRY* pEntry = pMap->pEntry;
- ASSERT(pEntry != NULL);
- while (pEntry->piid != NULL)
- {
- if (((DWORD*)pEntry->piid)[0] == lData1 &&
- ((DWORD*)pEntry->piid)[1] == ((DWORD*)iid)[1] &&
- ((DWORD*)pEntry->piid)[2] == ((DWORD*)iid)[2] &&
- ((DWORD*)pEntry->piid)[3] == ((DWORD*)iid)[3])
- {
- // check INTERFACE_ENTRY macro
- LPUNKNOWN lpUnk = GetInterfacePtr(this, pEntry);
-
- // check vtable pointer (can be NULL)
- if (*(DWORD*)lpUnk != 0)
- return lpUnk;
- }
-
- // entry did not match -- keep looking
- ++pEntry;
- }
- #ifdef _AFXDLL
- } while ((pMap = (*pMap->pfnGetBaseMap)()) != NULL);
- #else
- } while ((pMap = pMap->pBaseMap) != NULL);
- #endif
-
- // interface ID not found, fail the call
- return NULL;
- }
-
- LPUNKNOWN CCmdTarget::QueryAggregates(const void* iid)
- {
- const AFX_INTERFACEMAP* pMap = GetInterfaceMap();
- ASSERT(pMap != NULL);
-
- // walk the Interface map to call aggregates
- do
- {
- const AFX_INTERFACEMAP_ENTRY* pEntry = pMap->pEntry;
- // skip non-aggregate entries
- ASSERT(pEntry != NULL);
- while (pEntry->piid != NULL)
- ++pEntry;
-
- // call QueryInterface for each aggregate entry
- while (pEntry->nOffset != (size_t)-1)
- {
- LPUNKNOWN lpQuery = GetAggregatePtr(this, pEntry);
- // it is ok to have aggregate but not created yet
- if (lpQuery != NULL)
- {
- LPUNKNOWN lpUnk = NULL;
- if (lpQuery->QueryInterface(*(IID*)iid, (LPLP)&lpUnk)
- == S_OK && lpUnk != NULL)
- {
- // QueryInterface successful...
- return lpUnk;
- }
- }
-
- // entry did not match -- keep looking
- ++pEntry;
- }
- #ifdef _AFXDLL
- } while ((pMap = (*pMap->pfnGetBaseMap)()) != NULL);
- #else
- } while ((pMap = pMap->pBaseMap) != NULL);
- #endif
-
- // interface ID not found, fail the call
- return NULL;
- }
-
- // real implementation of QueryInterface
- DWORD CCmdTarget::InternalQueryInterface(const void* iid, LPVOID* ppvObj)
- {
- // check local interfaces
- if ((*ppvObj = GetInterface(iid)) != NULL)
- {
- // interface was found -- add a reference
- ExternalAddRef();
- return S_OK;
- }
-
- // check aggregates
- if ((*ppvObj = QueryAggregates(iid)) != NULL)
- return S_OK;
-
- // interface ID not found, fail the call
- return (DWORD)E_NOINTERFACE;
- }
-
- // QueryInterface that is exported to normal clients
- DWORD CCmdTarget::ExternalQueryInterface(const void* iid,
- LPVOID* ppvObj)
- {
- // delegate to controlling unknown if aggregated
- if (m_pOuterUnknown != NULL)
- return m_pOuterUnknown->QueryInterface(*(IID*)iid, ppvObj);
-
- return InternalQueryInterface(iid, ppvObj);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Inner IUnknown implementation (for aggregation)
-
- STDMETHODIMP_(ULONG) CInnerUnknown::AddRef()
- {
- METHOD_PROLOGUE_(CCmdTarget, InnerUnknown)
- return pThis->InternalAddRef();
- }
-
- STDMETHODIMP_(ULONG) CInnerUnknown::Release()
- {
- METHOD_PROLOGUE(CCmdTarget, InnerUnknown)
- return pThis->InternalRelease();
- }
-
- STDMETHODIMP CInnerUnknown::QueryInterface(REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_(CCmdTarget, InnerUnknown)
-
- if (iid == IID_IUnknown)
- {
- // QueryInterface on inner IUnknown for IID_IUnknown must
- // return inner IUnknown.
- pThis->InternalAddRef();
- *ppvObj = this;
- return S_OK;
- }
- return pThis->InternalQueryInterface(&iid, ppvObj);
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // other helper functions
-
- // ExternalDisconnect is used to remove RPC connections in destructors. This
- // insures that no RPC calls will go to the object after it has been
- // deleted.
- void CCmdTarget::ExternalDisconnect()
- {
- if (m_dwRef == 0) // already in disconnected state?
- return;
-
- // get IUnknown pointer for the object
- LPUNKNOWN lpUnknown = (LPUNKNOWN)GetInterface(&IID_IUnknown);
- ASSERT(lpUnknown != NULL);
-
- // disconnect the object
- InterlockedIncrement(&m_dwRef); // protect object from destruction
- CoDisconnectObject(lpUnknown, 0);
- m_dwRef = 0; // now in disconnected state
- }
-
- // GetControllingUnknown is used when creating aggregate objects,
- // usually from OnCreateAggregates. The outer, or controlling, unknown
- // is one of the parameters to CoCreateInstance and other OLE creation
- // functions which support aggregation.
- LPUNKNOWN CCmdTarget::GetControllingUnknown()
- {
- if (m_pOuterUnknown != NULL)
- return m_pOuterUnknown; // aggregate of m_pOuterUnknown
-
- LPUNKNOWN lpUnknown = (LPUNKNOWN)GetInterface(&IID_IUnknown);
- return lpUnknown; // return our own IUnknown implementation
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Inline function declarations expanded out-of-line
-
- #ifndef _AFX_ENABLE_INLINES
-
- // expand inlines for OLE general APIs
- static char _szAfxOleInl[] = "afxole.inl";
- #undef THIS_FILE
- #define THIS_FILE _szAfxOleInl
- #define _AFXDISP_INLINE
- #include "afxole.inl"
-
- #endif //!_AFX_ENABLE_INLINES
-
- /////////////////////////////////////////////////////////////////////////////
-