⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util.cpp

📁 Windows CE 6.0 Word Application 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	// releasing cached interface pointers on your aggregatee.  We
	// can't put an assert here because we do this all the time now.
	//

	return m_cRefs;
}

//+-------------------------------------------------------------------------
//
//  Member: 	CSafeRefCount::SafeRelease
//
//  Synopsis:	decrements the reference count on the object
//
//  Effects: 	May delete the object!
//
//  Arguments:
//
//  Requires:
//
//  Returns:	ULONG -- the reference count after decrement
//
//  Signals:
//
//  Modifies:
//
//  Derivation:
//
//  Algorithm: 	decrements the reference count.  If the reference count
//				is zero AND the nest count is zero AND we are not currently
//				trying to delete our object, then it is safe to delete.
//
//  History:    dd-mmm-yy Author    Comment
//				28-Jul-94 alexgo    author
//
//  Notes:
//
//--------------------------------------------------------------------------

ULONG CSafeRefCount::SafeRelease()
{
	ULONG	cRefs;

	if( m_cRefs > 0 )
	{
		cRefs = --m_cRefs;

		if( m_cRefs == 0 && m_cNest == 0 && m_fInDelete == FALSE )
		{
			m_fInDelete = TRUE;
			delete this;
		}
	}
	else
	{
 		// somebody is releasing a non-addrefed pointer!!
		AssertSz(0, "Release called on a non-addref'ed pointer!\n");

		cRefs = 0;
	}

	return cRefs;
}

//+-------------------------------------------------------------------------
//
//  Member: 	CSafeRefCount::IncrementNestCount
//
//  Synopsis: 	increments the nesting count of the object
//
//  Effects:
//
//  Arguments: 	none
//
//  Requires:
//
//  Returns: 	ULONG; the nesting count after increment
//
//  Signals:
//
//  Modifies:
//
//  Derivation:
//
//  Algorithm:
//
//  History:    dd-mmm-yy Author    Comment
// 				28-Jul-94 alexgo    author
//
//  Notes:	The nesting count is the count of how many times an
//		an object has been re-entered.  For example, suppose
//		somebody calls pFoo->Bar1(), which makes some calls that
//		eventually call pFoo->Bar2();.  On entrace to Bar2, the
//		nest count of the object should be 2 (since the invocation
//		of Bar1 is still on the stack above us).
//
//		It is important to keep track of the nest count so we do
//		not accidentally delete ourselves during a nested invocation.
//		If we did, then when the stack unwinds to the original
//		top level call, it could try to access a non-existent member
//		variable and crash.
//
//--------------------------------------------------------------------------

ULONG CSafeRefCount::IncrementNestCount()
{

#ifdef DEBUG
	if( m_fInDelete )
	{
		TRACEWARNSZ("WARNING: CSafeRefCount, object "
			"re-entered during delete!\n");
	}
#endif

	m_cNest++;

	return m_cNest;
}

//+-------------------------------------------------------------------------
//
//  Member: 	CSafeRefCount::DecrementNestCount
//
//  Synopsis: 	decrements the nesting count and deletes the object
//				(if necessary)
//
//  Effects: 	may delete 'this' object!
//
//  Arguments: 	none
//
//  Requires:
//
//  Returns:	ULONG, the nesting count after decrement
//
//  Signals:
//
//  Modifies:
//
//  Derivation:
//
//  Algorithm:	decrements the nesting count.  If the nesting count is zero
//				AND the reference count is zero AND we are not currently
//				trying to delete ourselves, then delete 'this' object
//
//  History:    dd-mmm-yy Author    Comment
//				28-Jul-94 alexgo    author
//
//  Notes:
//
//--------------------------------------------------------------------------

ULONG CSafeRefCount::DecrementNestCount()
{
	ULONG	cNest;

	if( m_cNest > 0 )
	{
		cNest = --m_cNest;

		if( m_cRefs == 0 && m_cNest == 0 && m_fInDelete == FALSE )
		{
			m_fInDelete = TRUE;
			delete this;
		}
	}
	else
	{
 		// somebody forget to increment the nest count!!
		AssertSz(0, "Unbalanced nest count!!");

		cNest = 0;
	}

	return cNest;
}

//+-------------------------------------------------------------------------
//
//  Member:  	CSafeRefCount::IsZombie
//
//  Synopsis: 	determines whether or not the object is in a zombie state
//				(i.e. all references gone, but we are still on the stack
//				somewhere).
//
//  Effects:
//
//  Arguments:	none
//
//  Requires:
//
//  Returns: 	TRUE if in a zombie state
//				FALSE otherwise
//
//  Signals:
//
//  Modifies:
//
//  Derivation:
//
//  Algorithm:  If we are in the middle of a delete, or if the ref count
//				is zero and the nest count is greater than zero, then we
//				are a zombie
//
//  History:    dd-mmm-yy Author    Comment
// 				28-Jul-94 alexgo    author
//
//  Notes:
//
//--------------------------------------------------------------------------

BOOL CSafeRefCount::IsZombie()
{
	BOOL	fIsZombie;

	if( (m_cRefs == 0 && m_cNest > 0) || m_fInDelete == TRUE
	    || m_fForceZombie == TRUE)
	{
		fIsZombie = TRUE;
	}
	else
	{
		fIsZombie = FALSE;
	}

	return fIsZombie;
}

//+-------------------------------------------------------------------------
//
//  Member:  	CSafeRefCount::Zombie
//
//  Synopsis: 	Forces the object into a zombie state.  This is called
//              when the object is still around but shouldn't be. It
//              flags us so we behave safely while we are in this state.
//
//  Effects:
//
//  Arguments:	none
//
//  Requires:
//
//  Returns:    none
//
//  Signals:
//
//  Modifies:
//
//  Derivation:
//
//  Algorithm:
//
//  History:
//
//  Notes:
//
//--------------------------------------------------------------------------

VOID CSafeRefCount::Zombie()
{
    m_fForceZombie = TRUE;
}

/* OleStdSwitchDisplayAspect
**
**	@mfunc
**    Switch the currently cached display aspect between DVASPECT_ICON
**    and DVASPECT_CONTENT.
**
**    NOTE: when setting up icon aspect, any currently cached content
**    cache is discarded and any advise connections for content aspect
**    are broken.
**
**	@rdesc
**      S_OK -- new display aspect setup successfully
**      E_INVALIDARG -- IOleCache interface is NOT supported (this is
**                  required).
**      <other SCODE> -- any SCODE that can be returned by
**                  IOleCache::Cache method.
**      NOTE: if an error occurs then the current display aspect and
**            cache contents unchanged.
*/
HRESULT OleStdSwitchDisplayAspect(
		LPOLEOBJECT             lpOleObj,
		LPDWORD                 lpdwCurAspect,
		DWORD                   dwNewAspect,
		HGLOBAL                 hMetaPict,
		BOOL                    fDeleteOldAspect,
		BOOL                    fSetupViewAdvise,
		LPADVISESINK            lpAdviseSink,
		BOOL FAR*               lpfMustUpdate)
{
#ifndef PEGASUS
   LPOLECACHE      lpOleCache = NULL;
   LPVIEWOBJECT    lpViewObj = NULL;
   LPENUMSTATDATA  lpEnumStatData = NULL;
   STATDATA        StatData;
   FORMATETC       FmtEtc;
   STGMEDIUM       Medium;
   DWORD           dwAdvf;
   DWORD           dwNewConnection;
   DWORD           dwOldAspect = *lpdwCurAspect;
   HRESULT         hrErr;

   if (lpfMustUpdate)
      *lpfMustUpdate = FALSE;

   if (hrErr =
	   lpOleObj->QueryInterface(IID_IOleCache, (void**)&lpOleCache))
   {
	   return hrErr;
   }

   // Setup new cache with the new aspect
   FmtEtc.cfFormat = 0;     // whatever is needed to draw
   FmtEtc.ptd      = NULL;
   FmtEtc.dwAspect = dwNewAspect;
   FmtEtc.lindex   = -1;
   FmtEtc.tymed    = TYMED_NULL;

   /* NOTE: if we are setting up Icon aspect with a custom icon
   **    then we do not want DataAdvise notifications to ever change
   **    the contents of the data cache. thus we set up a NODATA
   **    advise connection. otherwise we set up a standard DataAdvise
   **    connection.
   */
   if (dwNewAspect == DVASPECT_ICON && hMetaPict)
      dwAdvf = ADVF_NODATA;
   else
      dwAdvf = ADVF_PRIMEFIRST;

   hrErr = lpOleCache->Cache(
         (LPFORMATETC)&FmtEtc,
         dwAdvf,
         (LPDWORD)&dwNewConnection
   );

   if (! SUCCEEDED(hrErr)) {
      lpOleCache->Release();
      return hrErr;
   }

   *lpdwCurAspect = dwNewAspect;

   /* NOTE: if we are setting up Icon aspect with a custom icon,
   **    then stuff the icon into the cache. otherwise the cache must
   **    be forced to be updated. set the *lpfMustUpdate flag to tell
   **    caller to force the object to Run so that the cache will be
   **    updated.
   */
   if (dwNewAspect == DVASPECT_ICON && hMetaPict) {

      FmtEtc.cfFormat = CF_METAFILEPICT;
      FmtEtc.ptd      = NULL;
      FmtEtc.dwAspect = DVASPECT_ICON;
      FmtEtc.lindex   = -1;
      FmtEtc.tymed    = TYMED_MFPICT;

      Medium.tymed            = TYMED_MFPICT;
      Medium.hGlobal        = hMetaPict;
      Medium.pUnkForRelease   = NULL;

      hrErr = lpOleCache->SetData(
            (LPFORMATETC)&FmtEtc,
            (LPSTGMEDIUM)&Medium,
            FALSE   /* fRelease */
      );
   } else {
      if (lpfMustUpdate)
         *lpfMustUpdate = TRUE;
   }

   if (fSetupViewAdvise && lpAdviseSink) {
      /* NOTE: re-establish the ViewAdvise connection */
      lpOleObj->QueryInterface(IID_IViewObject, (void**)&lpViewObj);

      if (lpViewObj) {

         lpViewObj->SetAdvise(
               dwNewAspect,
               0,
               lpAdviseSink
         );

         lpViewObj->Release();
      }
   }

   /* NOTE: remove any existing caches that are set up for the old
   **    display aspect. It WOULD be possible to retain the caches set
   **    up for the old aspect, but this would increase the storage
   **    space required for the object and possibly require additional
   **    overhead to maintain the unused cachaes. For these reasons the
   **    strategy to delete the previous caches is prefered. if it is a
   **    requirement to quickly switch between Icon and Content
   **    display, then it would be better to keep both aspect caches.
   */

   if (fDeleteOldAspect) {
      hrErr = lpOleCache->EnumCache(
            (LPENUMSTATDATA FAR*)&lpEnumStatData
      );

      while(hrErr == NOERROR) {
         hrErr = lpEnumStatData->Next(
               1,
               (LPSTATDATA)&StatData,
               NULL
         );
         if (hrErr != NOERROR)
            break;              // DONE! no more caches.

         if (StatData.formatetc.dwAspect == dwOldAspect) {

            // Remove previous cache with old aspect
            lpOleCache->Uncache(StatData.dwConnection);
         }
      }

      if (lpEnumStatData)
         lpEnumStatData->Release();
   }

   if (lpOleCache)
      lpOleCache->Release();
#endif
   return NOERROR;
}

/*
 *	ObjectReadSiteFlags
 *
 *	@mfunc
 *		Read the dwFlags, dwUser, & dvaspect bytes from a container
 *		specific stream.
 *
 *	Arguments:
 *		preobj			The REOBJ in which to copy the flags.
 *
 *	@rdesc
 *		HRESULT
 */
HRESULT ObjectReadSiteFlags(REOBJECT * preobj)
{
	HRESULT hr = NOERROR;
#ifndef PEGASUS
	LPSTREAM pstm = NULL;
	OLECHAR StreamName[] = OLESTR("RichEditFlags");


	// Make sure we have a storage to read from
	if (!preobj->pstg)
		return E_INVALIDARG;

	// Open the stream
	if (hr = preobj->pstg->OpenStream(StreamName, 0, STGM_READ |
										STGM_SHARE_EXCLUSIVE, 0, &pstm))
	{
		goto Cleanup;
	}

	if ((hr = pstm->Read(&preobj->dwFlags,
							sizeof(preobj->dwFlags), NULL)) ||
		(hr = pstm->Read(&preobj->dwUser,
							 sizeof(preobj->dwUser), NULL)) ||
		(hr = pstm->Read(&preobj->dvaspect,
								 sizeof(preobj->dvaspect), NULL)))
	{
		goto Cleanup;
	}

Cleanup:
	if (pstm)
		pstm->Release();
#endif
	return hr;
}

//Used for EnumMetafileCheckIcon & FIsIconMetafilePict
typedef	struct _walkmetafile
{
	BOOL	fAND;
	BOOL	fPastIcon;
	BOOL 	fHasIcon;
} WALKMETAFILE;

static CHAR szIconOnly[] = "IconOnly";

/*
 * EnumMetafileCheckIcon
 *
 * @mfunc
 *	Stripped down version of EnumMetafileExtractIcon and
 *	EnumMetafileExtractIconSource from the OLE2UI library.
 *
 *  EnumMetaFile callback function that walks a metafile looking for
 *  StretchBlt (3.1) and BitBlt (3.0) records.  We expect to see two
 *  of them, the first being the AND mask and the second being the XOR
 *  data. 
 *
 *	Once we find the icon, we confirm this find by looking for the "IconOnly"
 *	comment block found in standard OLE iconic metafiles.
 *
 *  Arguments:
 *		hDC             HDC into which the metafile should be played.
 *		phTable         HANDLETABLE FAR * providing handles selected into the DC.
 *		pMFR            METARECORD FAR * giving the enumerated record.
 *		pIE             LPICONEXTRACT providing the destination buffer and length.
 *
 * @rdesc
 *  int             0 to stop enumeration, 1 to continue.
 */

int CALLBACK EnumMetafileCheckIcon(HDC hdc, HANDLETABLE *phTable,
											METARECORD *pMFR, int cObj,
											LPARAM lparam)
{
#ifndef PEGASUS
	WALKMETAFILE *		pwmf = (WALKMETAFILE *) lparam;

	switch (pMFR->rdFunction)
	{
	case META_DIBBITBLT:			// Win30
	case META_DIBSTRETCHBLT:		// Win31
		// If this is the first pass (pIE->fAND==TRUE) then save the memory
		// of the AND bits for the next pass.

		if (pwmf->fAND)
			pwmf->fAND = FALSE;
		else
			pwmf->fPastIcon = TRUE;
		break;

	case META_ESCAPE:
		if (pwmf->fPastIcon &&
			pMFR->rdParm[0] == MFCOMMENT &&
			!lstrcmpiA(szIconOnly, (LPSTR)&pMFR->rdParm[2]))
		{
			pwmf->fHasIcon = TRUE;
			return 0;
		}
		break;
	}
#endif
	return 1;
}

/*
 *	FIsIconMetafilePict
 *
 *	@mfunc
 *		Detect whether the metafile contains an iconic presentation. We do this
 *		by getting a screen DC and walking the metafile records until we find
 *		the landmarks denoting an icon.
 *
 *		Arguments:
 *			hmfp			The metafile to test
 *
 *	@rdesc
 *		BOOL			TRUE if the metafile contains an iconic view
 */
BOOL FIsIconMetafilePict(HGLOBAL hmfp)
{
#ifndef PEGASUS
	LPMETAFILEPICT	pmfp;
	WALKMETAFILE	wmf = { 0 };
	HDC				hdc;

	wmf.fAND = TRUE;
	if (!hmfp || !(pmfp = (LPMETAFILEPICT)GlobalLock(hmfp)))
		goto CleanUp;

	// We get information back in the ICONEXTRACT structure.
	hdc = GetDC(NULL);
	EnumMetaFile(hdc, pmfp->hMF, EnumMetafileCheckIcon, (LPARAM) &wmf);
	ReleaseDC(NULL, hdc);
	GlobalUnlock(hmfp);

CleanUp:
	return wmf.fHasIcon;
#else
	return TRUE;
#endif
}

/*
 * AllocObjectDescriptor
 *
 * Purpose:
 *  Allocated and fills an OBJECTDESCRIPTOR structure.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -