Пример #1
0
HRESULT CDataAdviseCache::EnumAndAdvise(LPDATAOBJECT pDataDelegate,
		BOOL fAdvise)
{
	VDATEHEAP();

	VDATEIFACE(pDataDelegate);
	LPENUMSTATDATA penumAdvise; // enumerator for the data advise holder
	DWORD dwDelegate; // delegate connection id for the current connection
	STATDATA statdata; // filled in by the penumAdvise enumerator
	HRESULT hresult = NOERROR; // current error status

	// get an enumerator from the data advise holder
	RetErr(m_pDAH->EnumAdvise(&penumAdvise));

	// repeat for each advise sink in the data advise holder...
	while(NOERROR == penumAdvise->Next(1, &statdata, NULL))
	{
		if(fAdvise)
		{
			// It is possible that the delegate's Advise will fail
			// even though we allowed the advise on the loaded
			// object to succeed(because the delegate is "pickier".)
			if(NOERROR==pDataDelegate->DAdvise(&statdata.formatetc,
					statdata.advf, statdata.pAdvSink,
					&dwDelegate))
			{
				// we know the key is present; this SetAt
				// should not fail
				Verify(m_mapClientToDelegate.SetAt(
						statdata.dwConnection,
						dwDelegate));
			}
		}
		else // unadvise
		{
			if((hresult=ClientToDelegate(statdata.dwConnection,
					&dwDelegate)) != NOERROR)
			{
				AssertSz(0, "Corrupt mapping");
				UtReleaseStatData(&statdata);
				goto errRtn;
			}
				
			if(dwDelegate != 0)
			{
				if(NOERROR==pDataDelegate->DUnadvise(
						dwDelegate))
				{
					// we know the key is present; this
					// SetAt should not fail
					Verify(m_mapClientToDelegate.SetAt(
							statdata.dwConnection,
							0));
				}
				else
				{
					LEDebugOut((DEB_IWARN,
					"WARNING: Delegate rejected unadvise\n"));
					;
				}
			}
		}
		UtReleaseStatData(&statdata);
	}

  errRtn:

	// release the enumerator
	penumAdvise->Release();
	return hresult;
}
Пример #2
0
HRESULT CDataAdviseCache::Advise(LPDATAOBJECT pDataObject,
		FORMATETC FAR* pFetc, DWORD advf, LPADVISESINK pAdvise,
		DWORD FAR* pdwClient)
		// first 4 parms are as in DataObject::Advise
{
	VDATEHEAP();

	DWORD dwDelegate = 0; // the delegate connection number
	HRESULT hr;

	// if there is a data object, ask to be advised of changes
	if(pDataObject != NULL)
		RetErr(pDataObject->DAdvise(pFetc, advf, pAdvise, &dwDelegate));

	// if there is no data object, (i.e. the object is not active,
	// dwDelegate is zero

	// Here we are using the data advise holder only to hold advise
	// connections. We are not going to use it to send OnDataChange to
	// sinks.
	
	// REVIEW, handling of ADVF_ONLYONCE seems broken...
	// it's clear that we can't cope with this flag properly;  we have
	// no way of knowing when the notification takes place, and therefore
	// we can't remove the entry from m_pDAH.  The notification may have
	// taken place above, and it may not have.  If the data object wasn't
	// around, then the advise request here is lost, and the sink will
	// never be notified.  Or, if the request isn't PRIMEFIRST, and the
	// data object is deactivated, then the data object loses the request,
	// and on subsequent activation, we won't readvise it on EnumAndAdvise.
	// So, what good are we for ONLYONCE sinks?  What does this break?
	if(advf & ADVF_ONLYONCE)
		return  NOERROR;

	// keep a local copy of the advise
	hr = m_pDAH->Advise(NULL, pFetc, advf, pAdvise, pdwClient);

	// if we failed to keep a local reference to the advise sink,
	// we won't be able to maintain this mapping, so remove the
	// advise on the data object, if there is one
	if (hr != NOERROR)
	{
	Exit1:
		if (pDataObject != NULL)
			pDataObject->DUnadvise(dwDelegate);

		return(hr);
	}

	// create a map entry from *pdwClient -> dwDelegate

	// if the map entry creation failed, undo all work
	if (m_mapClientToDelegate.SetAt(*pdwClient, dwDelegate) != TRUE)
	{
		// map failed to allocate memory, undo advise since we won't
		// be able to find this one again
		m_pDAH->Unadvise(*pdwClient);

		// map entry creation must have failed from lack of allocation
		hr = ReportResult(0, E_OUTOFMEMORY, 0, 0);

		// undo the advise on the data object
		goto Exit1;
	}

	return(NOERROR);
}