mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
788 lines
17 KiB
788 lines
17 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1993 - 1993.
|
|
//
|
|
// File: cantimon.cxx
|
|
//
|
|
// Contents:
|
|
//
|
|
// Classes:
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 12-27-93 ErikGav Did not write this code
|
|
// 02-04-94 KevinRo Gag'd on it, then rewrote it
|
|
// 06-14-94 Rickhi Fix type casting
|
|
//
|
|
// An Anti moniker is intended to be the inverse of any moniker, such as
|
|
// an Item Moniker. When another moniker composes itself with an Anti moniker
|
|
// on the right, it is supposed to remove itself from the result.
|
|
//
|
|
// The original implementation of Anti monikers attempted to be optimal by
|
|
// collapsing itself when composed with another Anti moniker. This was an
|
|
// unfortunate decision, since other monikers decide to eliminate themselves
|
|
// (and the Anti moniker) based on whether the moniker type to the right is
|
|
// an Anti moniker.
|
|
//
|
|
// For example, File moniker (F) composed with an Anti moniker (A) should
|
|
// result in nothing. F o A == (). The previous implementation was in error
|
|
// because a composite of two anti-monikers was treated as a single anti
|
|
// moniker with a count of two, denoted A(2).
|
|
// Therefore, when the file moniker looked at the anti moniker using the
|
|
// interface, it saw only one Anti moniker, instead of a composite.
|
|
// ( F o A(2)) == (). It should have been ( F o (A o A) ) == ( A )
|
|
//
|
|
// To fix this, when we compose Anti monikers, we will always use a
|
|
// composite. We need to be careful when loading old serialized Anti
|
|
// monikers, and convert them as we see them.
|
|
//
|
|
// This actually makes this a sucky problem, since old monikers have a
|
|
// funny behaviour if loaded from stream. The way the Load() interface
|
|
// works, the client has a pointer to the Anti moniker before it is loaded.
|
|
// Therefore, we can't just magically make this work.
|
|
//
|
|
// However, we can fix this up as soon as we can during the first Reduce or
|
|
// Compose with that is called. You will find this code in the Compose
|
|
// with methods, plus in the Create(count) methods.
|
|
//
|
|
// Save() is also a problem, since the caller has already written out our
|
|
// class ID. Therefore, we can't just sneak in a composite, since it will
|
|
// break the old fellows.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include <ole2int.h>
|
|
|
|
#include "cbasemon.hxx"
|
|
#include "cantimon.hxx"
|
|
#include "mnk.h"
|
|
|
|
|
|
|
|
INTERNAL_(CAntiMoniker *) IsAntiMoniker( LPMONIKER pmk )
|
|
{
|
|
CAntiMoniker *pCAM;
|
|
|
|
if ((pmk->QueryInterface(CLSID_AntiMoniker, (void **)&pCAM)) == S_OK)
|
|
{
|
|
// we release the AddRef from QI but stll return the pointer.
|
|
pCAM->Release();
|
|
return pCAM;
|
|
}
|
|
|
|
// dont rely on user implementations to return NULL on failed QI
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CAntiMoniker::Create
|
|
//
|
|
// Synopsis: Create a single AntiMoniker
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Derivation:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 2-04-94 kevinro Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CAntiMoniker FAR *CAntiMoniker::Create()
|
|
{
|
|
CAntiMoniker FAR * pCAM = new CAntiMoniker();
|
|
if (pCAM)
|
|
{
|
|
pCAM->AddRef();
|
|
}
|
|
return pCAM;
|
|
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CAntiMoniker::Create
|
|
//
|
|
// Synopsis: Create a composite anti moniker.
|
|
//
|
|
// Effects: This function supports the 'old' way of creating Anti
|
|
// monikers, by creating [count] Anti monikers, and composing
|
|
// them together.
|
|
//
|
|
// Arguments: [count] -- Number of Anti monikers
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
// if count == 1, this routine will return an CAntiMoniker.
|
|
// if count > 1, this routine will create a composite moniker made up
|
|
// of Anti monikers.
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Derivation:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 2-04-94 kevinro Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
IMoniker * CAntiMoniker::Create(ULONG count)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::Create(0x%x))\n",
|
|
count));
|
|
|
|
|
|
HRESULT hr;
|
|
IMoniker *pmkComposite = NULL;
|
|
|
|
while(count--)
|
|
{
|
|
IMoniker *pmkNew;
|
|
|
|
CAntiMoniker FAR * pCAM = new CAntiMoniker();
|
|
|
|
//
|
|
// If there was failure, then releasing the old composite is
|
|
// required.
|
|
//
|
|
|
|
if (pCAM == NULL)
|
|
{
|
|
if (pmkComposite != NULL)
|
|
{
|
|
pmkComposite->Release();
|
|
}
|
|
return(NULL);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The ref counting mechanism originally choosen makes it the
|
|
// responsibility of the Create() routine to do the AddRef on
|
|
// the newly created moniker.
|
|
//
|
|
|
|
pCAM->AddRef();
|
|
}
|
|
|
|
//
|
|
// Create a generic composite using the existing and new
|
|
// monikers. If this succeededs, then pmkNew will increment
|
|
// both reference counts.
|
|
//
|
|
//
|
|
// If there was a failure, then calling Release() on the new and
|
|
// old sections of the composite will cause both of them to be
|
|
// released, thus releasing the entire tree of monikers.
|
|
//
|
|
// If it succeeds, pmkNew will hold references to both of the
|
|
// old monikers, and life will be good.
|
|
//
|
|
// Note: First time around, pmkComposite == NULL, and
|
|
// CreateGenericComposite() will just return pCAM. It works.
|
|
//
|
|
|
|
hr = CreateGenericComposite(pmkComposite,pCAM,&pmkNew);
|
|
|
|
pCAM->Release();
|
|
|
|
//
|
|
// Watch out for the first time around the loop. This will
|
|
// cause pmkComposite to be NULL
|
|
//
|
|
if (pmkComposite != NULL)
|
|
{
|
|
pmkComposite->Release();
|
|
}
|
|
|
|
//
|
|
// If failed, then the last two releases cleaned up for us.
|
|
//
|
|
if (FAILED(hr))
|
|
{
|
|
return(NULL);
|
|
}
|
|
|
|
pmkComposite = pmkNew;
|
|
}
|
|
|
|
return pmkComposite;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::QueryInterface(THIS_ REFIID riid,
|
|
LPVOID FAR* ppvObj)
|
|
{
|
|
M_PROLOG(this);
|
|
VDATEIID (riid);
|
|
VDATEPTROUT(ppvObj, LPVOID);
|
|
|
|
#ifdef _DEBUG
|
|
if (riid == IID_IDebug)
|
|
{
|
|
*ppvObj = &(m_Debug);
|
|
return NOERROR;
|
|
}
|
|
#endif
|
|
|
|
if (IsEqualIID(riid, CLSID_AntiMoniker))
|
|
{
|
|
// called by IsAntiMoniker.
|
|
AddRef();
|
|
*ppvObj = this;
|
|
return S_OK;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IROTData))
|
|
{
|
|
// called by ROT
|
|
AddRef();
|
|
*ppvObj = (IROTData *)this;
|
|
return S_OK;
|
|
}
|
|
|
|
return CBaseMoniker::QueryInterface(riid, ppvObj);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CAntiMoniker::Release(void)
|
|
{
|
|
M_PROLOG(this);
|
|
Assert(m_refs != 0);
|
|
|
|
ULONG ul = m_refs;
|
|
|
|
if (InterlockedDecrement((long *)&m_refs) == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return ul - 1;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::GetClassID(LPCLSID lpClassId)
|
|
{
|
|
M_PROLOG(this);
|
|
VDATEPTROUT(lpClassId, CLSID);
|
|
|
|
*lpClassId = CLSID_AntiMoniker;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::Load(LPSTREAM pStm)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::Load(%x)\n",
|
|
this));
|
|
|
|
M_PROLOG(this);
|
|
VDATEIFACE(pStm);
|
|
|
|
HRESULT hresult;
|
|
ULONG count;
|
|
|
|
hresult = StRead(pStm, &count, sizeof(ULONG));
|
|
|
|
if (SUCCEEDED(hresult))
|
|
{
|
|
m_count = count;
|
|
}
|
|
return hresult;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::Save(LPSTREAM pStm, BOOL fClearDirty)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::Save(%x)\n",
|
|
this));
|
|
|
|
M_PROLOG(this);
|
|
VDATEIFACE(pStm);
|
|
|
|
UNREFERENCED(fClearDirty);
|
|
ULONG cbWritten;
|
|
|
|
return pStm->Write(&m_count, sizeof(ULONG), &cbWritten);
|
|
// REVIEW: what is proper error handling? Should we restore the seek
|
|
// pointer?
|
|
}
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::GetSizeMax(ULARGE_INTEGER FAR* pcbSize)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::GetSizeMax(%x)\n",
|
|
this));
|
|
|
|
M_PROLOG(this);
|
|
VDATEPTROUT(pcbSize, ULONG);
|
|
|
|
ULISet32(*pcbSize, sizeof(CLSID) + sizeof(ULONG));
|
|
noError;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CAntiMoniker::ComposeWith
|
|
//
|
|
// Synopsis: Compose this moniker with another moniker.
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments: [pmkRight] --
|
|
// [fOnlyIfNotGeneric] --
|
|
// [ppmkComposite] --
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Derivation:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 2-04-94 kevinro Created
|
|
//
|
|
// Notes:
|
|
//
|
|
// In the event that m_count > 1, we can use this opportunity to fixup the
|
|
// anti moniker into a composite of single anti monikers. This will help make
|
|
// the monikers work correctly.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CAntiMoniker::ComposeWith( LPMONIKER pmkRight,
|
|
BOOL fOnlyIfNotGeneric, LPMONIKER FAR* ppmkComposite)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::ComposeWith(%x,pmkRight(%x))\n",
|
|
this,
|
|
pmkRight));
|
|
|
|
VDATEPTROUT(ppmkComposite,LPMONIKER);
|
|
*ppmkComposite = NULL;
|
|
VDATEIFACE(pmkRight);
|
|
|
|
HRESULT hresult = NOERROR;
|
|
IMoniker *pmkThis = NULL;
|
|
IMoniker *pmkRightComposite = NULL;
|
|
|
|
|
|
//
|
|
// The only way CAntiMonikers can compose is generically
|
|
//
|
|
if (fOnlyIfNotGeneric)
|
|
{
|
|
hresult = MK_E_NEEDGENERIC;
|
|
*ppmkComposite = NULL;
|
|
return hresult;
|
|
}
|
|
|
|
//
|
|
// Now, we are going to make a generic composite. This is a
|
|
// good time to determine if we need to convert this
|
|
// anti moniker into a composite
|
|
//
|
|
// If m_count > 1, create an equivalent composite moniker
|
|
//
|
|
|
|
if (m_count > 1)
|
|
{
|
|
pmkThis = Create(m_count);
|
|
}
|
|
|
|
//
|
|
// Regardless of the outcome, be sure pmkThis == a moniker to
|
|
// compose with.
|
|
//
|
|
|
|
if (pmkThis == NULL)
|
|
{
|
|
pmkThis = this;
|
|
}
|
|
|
|
//
|
|
// If the right side is an anti moniker also, then we need to
|
|
// concatenate the two Anti monikers into a composite.
|
|
//
|
|
|
|
CAntiMoniker *pmkRightAnti = IsAntiMoniker(pmkRight);
|
|
if (pmkRightAnti)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"::ComposeWith(%x) CAntiMoniker(%x)\n",
|
|
this,
|
|
pmkRight));
|
|
|
|
//
|
|
// The right side is also an Anti moniker. Does it need fixing
|
|
// as well? If so, then fix it up, and assign it to pmkRight
|
|
//
|
|
|
|
if (pmkRightAnti->m_count > 1 )
|
|
{
|
|
pmkRightComposite = CAntiMoniker::Create(m_count);
|
|
|
|
if (pmkRightComposite != NULL)
|
|
{
|
|
pmkRight = pmkRightComposite;
|
|
}
|
|
}
|
|
|
|
hresult = Concatenate(pmkThis,pmkRight,ppmkComposite);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Anti monikers can only be composed using generic composites
|
|
// when they are on the left.
|
|
//
|
|
|
|
hresult = CreateGenericComposite( pmkThis,
|
|
pmkRight,
|
|
ppmkComposite );
|
|
}
|
|
|
|
//
|
|
// Clean up after possible conversions
|
|
//
|
|
|
|
if (pmkThis != this)
|
|
{
|
|
pmkThis->Release();
|
|
}
|
|
|
|
if (pmkRightComposite != NULL)
|
|
{
|
|
pmkRightComposite->Release();
|
|
}
|
|
|
|
return hresult;
|
|
}
|
|
|
|
STDMETHODIMP CAntiMoniker::Enum (THIS_ BOOL fForward, LPENUMMONIKER FAR* ppenumMoniker)
|
|
{
|
|
VDATEPTROUT(ppenumMoniker,LPENUMMONIKER);
|
|
*ppenumMoniker = NULL;
|
|
noError;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CAntiMoniker::GetComparisonData
|
|
//
|
|
// Synopsis: Get comparison data for registration in the ROT
|
|
//
|
|
// Arguments: [pbData] - buffer to put the data in.
|
|
// [cbMax] - size of the buffer
|
|
// [pcbData] - count of bytes used in the buffer
|
|
//
|
|
// Returns: NOERROR
|
|
// E_OUTOFMEMORY
|
|
//
|
|
// Algorithm: Build ROT data for anti moniker.
|
|
//
|
|
// History: 03-Feb-95 kevinro Created
|
|
//
|
|
// Note: Validating the arguments is skipped intentionally because this
|
|
// will typically be called internally by OLE with valid buffers.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
STDMETHODIMP CAntiMoniker::GetComparisonData(
|
|
byte *pbData,
|
|
ULONG cbMax,
|
|
DWORD *pcbData)
|
|
{
|
|
ULONG ulLength = sizeof(CLSID_AntiMoniker) + sizeof(m_count);
|
|
|
|
Assert(pcbData != NULL);
|
|
Assert(pbData != NULL);
|
|
|
|
if (cbMax < ulLength)
|
|
{
|
|
return(E_OUTOFMEMORY);
|
|
}
|
|
|
|
memcpy(pbData,&CLSID_AntiMoniker,sizeof(CLSID_AntiMoniker));
|
|
memcpy(pbData+sizeof(CLSID_AntiMoniker),&m_count,sizeof(m_count));
|
|
|
|
*pcbData = ulLength;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CAntiMoniker::IsEqual (THIS_ LPMONIKER pmkOtherMoniker)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::IsEqual(%x,pmkOther(%x))\n",
|
|
this,
|
|
pmkOtherMoniker));
|
|
|
|
VDATEIFACE(pmkOtherMoniker);
|
|
|
|
CAntiMoniker *pCAM = IsAntiMoniker(pmkOtherMoniker);
|
|
|
|
if (pCAM)
|
|
{
|
|
// the other moniker is an anti moniker.
|
|
if (m_count == pCAM->m_count)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
}
|
|
|
|
return ResultFromScode(S_FALSE);
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::Hash (THIS_ LPDWORD pdwHash)
|
|
{
|
|
VDATEPTROUT(pdwHash, DWORD);
|
|
*pdwHash = 0x80000000 + m_count;
|
|
noError;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::CommonPrefixWith (LPMONIKER pmkOther, LPMONIKER FAR*
|
|
ppmkPrefix)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::CommonPrefixWith(%x,pmkOther(%x))\n",
|
|
this,
|
|
pmkOther));
|
|
|
|
M_PROLOG(this);
|
|
VDATEPTROUT(ppmkPrefix,LPMONIKER);
|
|
*ppmkPrefix = NULL;
|
|
VDATEIFACE(pmkOther);
|
|
|
|
CAntiMoniker *pAntiMoniker = IsAntiMoniker(pmkOther);
|
|
if (pAntiMoniker)
|
|
{
|
|
if (m_count <= pAntiMoniker->m_count)
|
|
{
|
|
*ppmkPrefix = this;
|
|
AddRef();
|
|
if (m_count == pAntiMoniker->m_count)
|
|
return ResultFromScode(MK_S_US);
|
|
return ResultFromScode(MK_S_ME);
|
|
}
|
|
*ppmkPrefix = pmkOther;
|
|
pmkOther->AddRef();
|
|
return ResultFromScode(MK_S_HIM);
|
|
}
|
|
return MonikerCommonPrefixWith(this, pmkOther, ppmkPrefix);
|
|
// this handles the case where pmkOther is composite, as well as
|
|
// all other cases.
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::RelativePathTo (THIS_ LPMONIKER pmkOther, LPMONIKER FAR*
|
|
ppmkRelPath)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::RelativePathTo(%x,pmkOther(%x))\n",
|
|
this,
|
|
pmkOther));
|
|
|
|
VDATEPTROUT(ppmkRelPath,LPMONIKER);
|
|
VDATEIFACE(pmkOther);
|
|
|
|
*ppmkRelPath = NULL;
|
|
|
|
*ppmkRelPath = pmkOther;
|
|
pmkOther->AddRef();
|
|
|
|
return MK_S_HIM;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::GetDisplayName( LPBC pbc, LPMONIKER
|
|
pmkToLeft, LPWSTR FAR * lplpszDisplayName )
|
|
// return "\..\..\.. "
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::GetDisplayName(%x,pmkLeft(%x))\n",
|
|
this,
|
|
pmkToLeft));
|
|
|
|
M_PROLOG(this);
|
|
|
|
VDATEPTROUT(lplpszDisplayName, LPWSTR);
|
|
|
|
*lplpszDisplayName = NULL;
|
|
|
|
VDATEIFACE(pbc);
|
|
|
|
if (pmkToLeft) VDATEIFACE(pmkToLeft);
|
|
|
|
WCHAR FAR * lpch;
|
|
ULONG i;
|
|
ULONG ccDisplayName;
|
|
|
|
//
|
|
// ccDisplayName is the number of characters to allocate
|
|
//
|
|
// For each anti moniker, return one instance of '\..', which
|
|
// is 3 characters long. Also, add 1 for the terminating NULL
|
|
//
|
|
|
|
ccDisplayName = 1 + ( 3 * m_count );
|
|
|
|
*lplpszDisplayName = (WCHAR *)
|
|
CoTaskMemAlloc(sizeof(WCHAR) * ccDisplayName);
|
|
|
|
lpch = *lplpszDisplayName;
|
|
|
|
if (lpch == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//
|
|
// Concat a whole bunch of strings forming the display name for
|
|
// the anti moniker
|
|
//
|
|
for (i = m_count; i > 0; i-- , lpch += 3)
|
|
{
|
|
memcpy(lpch, L"\\..", 3 * sizeof(WCHAR));
|
|
}
|
|
|
|
*lpch = '\0';
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::ParseDisplayName( LPBC pbc,
|
|
LPMONIKER pmkToLeft, LPWSTR lpszDisplayName, ULONG FAR* pchEaten,
|
|
LPMONIKER FAR* ppmkOut)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::ParseDisplayName(%x,pmkLeft(%x)lpszName(%ws))\n",
|
|
this,
|
|
pmkToLeft,
|
|
WIDECHECK(lpszDisplayName)));
|
|
|
|
M_PROLOG(this);
|
|
VDATEPTROUT(ppmkOut,LPMONIKER);
|
|
*ppmkOut = NULL;
|
|
VDATEIFACE(pbc);
|
|
if (pmkToLeft) VDATEIFACE(pmkToLeft);
|
|
VDATEPTRIN(lpszDisplayName, WCHAR);
|
|
VDATEPTROUT(pchEaten,ULONG);
|
|
|
|
return ResultFromScode(E_NOTIMPL); // ParseDisplayName not implemented for AntiMonikers
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CAntiMoniker::IsSystemMoniker (THIS_ LPDWORD pdwType)
|
|
{
|
|
M_PROLOG(this);
|
|
*pdwType = MKSYS_ANTIMONIKER;
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CAntiMoniker::EatOne
|
|
//
|
|
// Synopsis: This function creates an appropriate Anti moniker
|
|
//
|
|
// Effects:
|
|
//
|
|
// Arguments: [ppmk] --
|
|
//
|
|
// Requires:
|
|
//
|
|
// Returns:
|
|
// if m_count == 1, returns NULL
|
|
// if m_count == 2, returns a CAntiMoniker
|
|
// if m_count > 2, returns a composite made up of anti monikers.
|
|
//
|
|
// Signals:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// Derivation:
|
|
//
|
|
// Algorithm:
|
|
//
|
|
// History: 2-04-94 kevinro Created
|
|
//
|
|
// Notes:
|
|
//
|
|
// Back in the days when monikers collapsed themselves, this routine was
|
|
// called in order to eat one of the counts. Now, it is used as a good place
|
|
// to throw in a conversion for composite anti-monikers.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
void CAntiMoniker::EatOne(LPMONIKER *ppmk)
|
|
{
|
|
mnkDebugOut((DEB_ITRACE,
|
|
"CAntiMoniker::EatOne(%x)\n",
|
|
this));
|
|
|
|
*ppmk = CAntiMoniker::Create(m_count - 1);
|
|
}
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
STDMETHODIMP_(void) NC(CAntiMoniker,CDebug)::Dump( IDebugStream FAR * pdbstm)
|
|
{
|
|
VOID_VDATEIFACE(pdbstm);
|
|
|
|
*pdbstm << "CAntiMoniker @" << (VOID FAR *)m_pAntiMoniker;
|
|
*pdbstm << '\n';
|
|
pdbstm->Indent();
|
|
*pdbstm << "Refcount is " << (int)(m_pAntiMoniker->m_refs) << '\n';
|
|
*pdbstm << "Anti count is " << (int)(m_pAntiMoniker->m_count) << '\n';
|
|
pdbstm->UnIndent();
|
|
}
|
|
|
|
STDMETHODIMP_(BOOL) NC(CAntiMoniker,CDebug)::IsValid( BOOL fSuspicious )
|
|
{
|
|
return ((LONG)(m_pAntiMoniker->m_refs) > 0);
|
|
// add more later, maybe
|
|
}
|
|
|
|
#endif
|