summaryrefslogtreecommitdiffstats
path: root/private/ole32/ole232/stdimpl/defutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'private/ole32/ole232/stdimpl/defutil.cpp')
-rw-r--r--private/ole32/ole232/stdimpl/defutil.cpp317
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;
+}
+
+