diff options
Diffstat (limited to 'private/ole32/ole232/stdimpl/defutil.cpp')
-rw-r--r-- | private/ole32/ole232/stdimpl/defutil.cpp | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/private/ole32/ole232/stdimpl/defutil.cpp b/private/ole32/ole232/stdimpl/defutil.cpp new file mode 100644 index 000000000..147ca54c1 --- /dev/null +++ b/private/ole32/ole232/stdimpl/defutil.cpp @@ -0,0 +1,317 @@ + +//+------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1993. +// +// File: defutil.cpp +// +// Contents: Implementations of utility functions for the default +// handler and default link objects +// +// Classes: none +// +// Functions: DuLockContainer +// DuSetClientSite +// DuGetClientSite +// DuCacheDelegate +// +// History: dd-mmm-yy Author Comment +// 11-Jan-94 alexgo added VDATEHEAP macros to every function +// 20-Nov-93 alexgo 32bit port +// +//-------------------------------------------------------------------------- + +#include <le2int.h> +#pragma SEG(defutil) + +#include <olerem.h> +#include <ole2dbg.h> + +ASSERTDATA +NAME_SEG(defutil) + + +//+------------------------------------------------------------------------- +// +// Function: DuLockContainer +// +// Synopsis: Calls IOleContainer->LockContainer from the given client site +// +// Effects: Unlocking the container may release the calling object. +// +// Arguments: [pCS] -- the client site from which to get +// the IOleContainer pointer +// [fLockNew] -- TRUE == lock, FALSE == unlock +// [pfLockCur] -- pointer to a flag with the current lock +// state +// +// Requires: +// +// Returns: void +// +// Signals: +// +// Modifies: +// +// Algorithm: +// +// History: dd-mmm-yy Author Comment +// 20-Nov-93 alexgo 32bit port +// +// Notes: +// +//-------------------------------------------------------------------------- + +#pragma SEG(DuLockContainer) +INTERNAL_(void) DuLockContainer(IOleClientSite FAR* pCS, BOOL fLockNew, + BOOL FAR*pfLockCur) +{ + VDATEHEAP(); + +#ifdef _DEBUG + BOOL fLocked = FALSE; // used only for debugging so don't waste + // the code space in the retail version +#endif // _DEBUG + + IOleContainer FAR* pContainer; + + //the double bang turns each into a true boolean + if (!!fLockNew == !!*pfLockCur) + { + // already locked as needed + return; + } + + // set flag to false first since unlocking container may release obj; + // we can just set to false since it is either already false or going + // to become false (don't set to true until we know the lock completed). + *pfLockCur = FALSE; + + if (pCS == NULL) + { + pContainer = NULL; + } + else + { + HRESULT hresult = pCS->GetContainer(&pContainer); + + // Excel 5 can return S_FALSE, pContainer == NULL + // so we can't use AssertOutPtrIface here since it + // expects all successful returns to provide a + // valid interface + + if (hresult != NOERROR) + { + pContainer = NULL; // just in case + } + } + if (pContainer != NULL) + { + // we assume that LockContainer will succeed first and + // and set the locked flag that was passed into us. This + // way, if LockContainer succeeeds, we won't access memory + // that could have potentially been blown away. + // If it *fails*, then we handle reset the flag (as our + // memory would not have been free'd) + + BOOL fLockOld = *pfLockCur; + *pfLockCur = fLockNew; + + if( pContainer->LockContainer(fLockNew) != NOERROR ) + { + //failure case, we were not deleted + *pfLockCur = fLockOld; + //fLocked is FALSE + } +#ifdef _DEBUG + else + { + fLocked = TRUE; + } +#endif // _DEBUG + + pContainer->Release(); + } + +#ifdef _DEBUG + if (!fLocked) + { + Puts("WARNING: couldn't lock/unlock container for clientsite:\n"); + DbgDumpObject(pCS,0); + } +#endif // _DEBUG +} + + +//+------------------------------------------------------------------------- +// +// Function: DuSetClientSite +// +// Synopsis: Called by the default handler and deflink SetClientSite +// implemenations; Releases the old client site (and unlocks +// its container), stores the client site (locking its +// container). +// +// Effects: +// +// Arguments: [fRunning] -- whether or not the delegate is running +// [pCSNew] -- the new client site +// [ppCSCur] -- a pointer to the original client site +// pointer. [*ppCSCur] will be reset +// to the new client site pointer. +// [pfLockCur] -- pointer to the fLocked flag, used by +// DuLockContainer. +// +// Requires: +// +// Returns: HRESULT +// +// Signals: +// +// Modifies: +// +// Algorithm: +// +// History: dd-mmm-yy Author Comment +// 22-Nov-93 alexgo 32bit port +// +// Notes: +// +//-------------------------------------------------------------------------- + +#pragma SEG(DuSetClientSite) +INTERNAL DuSetClientSite(BOOL fRunning, IOleClientSite FAR* pCSNew, + IOleClientSite FAR* FAR* ppCSCur, BOOL FAR*pfLockCur) +{ + VDATEHEAP(); + + if (pCSNew) + { + VDATEIFACE( pCSNew ); + } + + IOleClientSite FAR* pCSCur = *ppCSCur; + + if (pCSCur != NULL) + { + // Unlock the old container + if (fRunning) + { + DuLockContainer(pCSCur, FALSE, pfLockCur); + } + + pCSCur->Release(); + } + + // we've decided to keep the pointer that's been passed to us. So we + // must AddRef() + if ((pCSCur = pCSNew) != NULL) + { + pCSNew->AddRef(); + + // Lock the newcontainer + if (fRunning) + { + DuLockContainer(pCSNew, TRUE, pfLockCur); + } + } + + *ppCSCur = pCSCur; + + return NOERROR; +} + +//+------------------------------------------------------------------------- +// +// Function: DuCacheDelegate +// +// Synopsis: Retrieves the requested interface from [pUnk]. If [fAgg] is +// true, we release the pointer (so ref counts to not get +// obfuscated ;-) +// +// Effects: +// +// Arguments: [ppUnk] -- the object to QueryInterface on +// [iid] -- the requested interface +// [ppv] -- where to put the pointer to the interface +// [pUnkOuter] -- controlling unknown, if non-NULL indicates +// aggregation and release is called on it +// +// +// +// Requires: +// +// Returns: void *, the requested interface pointer +// +// Signals: +// +// Modifies: +// +// Algorithm: +// +// History: dd-mmm-yy Author Comment +// 29-Jun-94 alexgo better handle re-entrancy +// 20-Jun-94 alexgo updated to May '94 aggregation rules +// 22-Nov-93 alexgo 32bit port +// +// Notes: +// +//-------------------------------------------------------------------------- + +#pragma SEG(DuCacheDelegate) +INTERNAL_(void FAR*) DuCacheDelegate(IUnknown FAR** ppUnk, + REFIID iid, LPVOID FAR* ppv, IUnknown *pUnkOuter) +{ + VDATEHEAP(); + + if (*ppUnk != NULL && *ppv == NULL) + { + if ((*ppUnk)->QueryInterface (iid, ppv) == NOERROR) + { + // the QI may actually be an outgoing call so it + // is possible that ppUnk was released and set to + // NULL during our call. To make the default link + // and handler simpler, we check for that case and + // release any pointer we may have obtained + // from the QI + + if( *ppUnk == NULL ) + { + LEDebugOut((DEB_WARN, "WARNING: Delegate " + "released during QI, should be OK\n")); + if( *ppv ) + { + // this should never be a final + // release on the default handler + // since we are calling it from + // within a method in the default + // link object. Therefore, + // we do not need to guard this + // release + // + // in the case of the link object, + // this may be the final release + // on the proxies, but since they are + // not aggregated into the link + // object, that's OK. + + (*(IUnknown **)ppv)->Release(); + *ppv = NULL; + } + } + if( pUnkOuter && *ppv) + { + // we will keep the pointer but we don't want + // to bump the ref count of the aggregate, + // so we gotta do Release() on the controlling + // unknown. + pUnkOuter->Release(); + } + } + } + + return *ppv; +} + + |