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

📄 impienumunknown.cpp

📁 基于Intellution开发包的开发的OPC服务器
💻 CPP
字号:
// ImpIEnumUnknown.cpp
//
//  This file contains an implementation of an IEnumUnknown interface.
//  Note this is a fully 'generic' enumerator implementation.
//
//  Since the list of elements is buffered in the object
//  It is appropriate for enumerations with a 'reasonable' number of elements
//
//  There is no OPC or Server specific code here.
//
// See IEnumXXXX::Next in Win32SDK\OLE\Reference\Interfaces\IEnumXXXX
// for general guidelines for enumerators
//
//
//	(c) COPYRIGHT 1996-1998, INTELLUTION INC.
// ALL RIGHTS RESERVED
//
//
//	Functions defined in this module:
//
//			CImpIEnumUnknown::CImpIEnumUnknown()
//			CImpIEnumUnknown::~CImpIEnumUnknown()
//			CImpIEnumUnknown::AddRef()
//			CImpIEnumUnknown::Release()
//			CImpIEnumUnknown::QueryInterface()
//			CImpIEnumUnknown::Next()
//			CImpIEnumUnknown::Skip()
//			CImpIEnumUnknown::Reset()
//			CImpIEnumUnknown::Clone()
//
//
//
// Modification Log:
//	Vers	Date     By		Notes
//	----	-------- ---	-----
//	1.00	08/26/97 jra	Created
//	1.3		03/10/98 jra	Modified to be wizard generated and driver specific.
//

#define WIN32_LEAN_AND_MEAN

#include "OpcStdAfx.h"

#include "OPC.h"


////////////////////////////////////////////////////////////////
// CImpIEnumUnknown::CImpIEnumUnknown)_
//
// Constructor
//
// Parameters:
//  pUnkRef   - LPUNKNOWN to use for reference counting (the 'parent').
//  cUnk      - ULONG number of LPUNKNOWNs in prgUnk
//  prgUnk    - LPUNKNOWN to the array to enumerate (we will make a 
//              local copy).
//
////////////////////////////////////////////////////////////////
CImpIEnumUnknown::CImpIEnumUnknown(LPUNKNOWN		pUnkOuter, 
								   ULONG			lCount, 
								   LPUNKNOWN		*pUnkList, 
								   IMalloc			*pIMalloc)
{
	m_lRefCount		= 0;
	m_pUnkOuter		= pUnkOuter;
	m_lCurrentElem	= 0;
	m_lNumUnks		= lCount;
	m_pUnkList		= new LPUNKNOWN[(UINT)lCount];
	m_pIMalloc		= pIMalloc;

	if (NULL != m_pUnkList)
	{
		for (UINT i = 0; i < lCount; i++)
		{
			// Create a local copy of the IUnknown List
			// And AddRef to insure the objects are not deleted 
			// while the ENUM is using them!
			//
			m_pUnkList[i] = pUnkList[i];
			m_pUnkList[i]->AddRef();	
		}
	}

	return;
}


////////////////////////////////////////////////////////////////
// CImpIEnumUnknown::~CImpIEnumUnknown
//
// Destructor
//
////////////////////////////////////////////////////////////////
CImpIEnumUnknown::~CImpIEnumUnknown(void)
{
	unsigned int	i;


	if (NULL != m_pUnkList)
	{
		for (i = 0; i < m_lNumUnks; i++)
		{
			// Release each object since this ENUM is done with it
			// 
			m_pUnkList[i]->Release();	
		}
		delete [] m_pUnkList;
	}
	return;
}



////////////////////////////////////////////////////////////////
// CImpIEnumUnknown::QueryInterface()
//
// Purpose:
//  IUnknown members for CImpIEnumUnknown object.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIEnumUnknown::QueryInterface(REFIID		riid, 
											  LPVOID		*ppv)
{
	*ppv = NULL;

	// Enumerators are separate objects with their own
	// QueryInterface behavior.
	//
	if (IID_IUnknown == riid || IID_IEnumUnknown == riid)
	{
		*ppv = (LPVOID)this;
	}

	if (NULL != *ppv)
	{
		((LPUNKNOWN)*ppv)->AddRef();
		return S_OK;
	}

	return E_NOINTERFACE;
}


////////////////////////////////////////////////////////////////
// CImpIEnumUnknown::Release()
//
// Purpose:
//  IUnknown members for CImpIEnumUnknown object.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIEnumUnknown::AddRef(void)
{
	// Addref this object and also the 'parent' if any
	//
	InterlockedIncrement(&m_lRefCount);
	if(m_pUnkOuter != NULL) 
	{
		m_pUnkOuter->AddRef();
	}
	return m_lRefCount;
}


////////////////////////////////////////////////////////////////
// CImpIEnumUnknown::Release()
//
// Purpose:
//  IUnknown members for CImpIEnumUnknown object.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIEnumUnknown::Release(void)
{
	// Release this object and also the 'parent' if any
	//
	if(m_pUnkOuter != NULL) 
	{
		m_pUnkOuter->Release();
	}

	if (0L != InterlockedDecrement(&m_lRefCount))
	{
		return m_lRefCount;
	}

	delete this;
	return 0;
}


////////////////////////////////////////////////////////////////
// CImpIEnumUnknown::Next()
//
// Purpose:
//  Returns the next element in the enumeration.
//
// Parameters:
//  cRequested  - ULONG max number of LPUNKNOWNs to return.
//  ppUnk       - LPUNKNOWN * in which to store the returned
//				  pointer.
//  pActual     - ULONG * in which to return how many we actually
//                enumerated.
//
// Return Value:
//  HRESULT     - S_OK if successful, S_FALSE otherwise,
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIEnumUnknown::Next(ULONG			cRequested, 
									IUnknown		**ppUnk, 
									ULONG			*pActual)
{
	ULONG		cReturn	 = 0L,
				maxcount = cRequested;


	*pActual = 0L;		// default
	*ppUnk = NULL;		// default

	// If this enumerator is empty - return FALSE
	//
	if (NULL == m_pUnkList)
	{
		return S_FALSE;
	}

	// If user passed null for count of items returned
	// Then he is only allowed to ask for 1 item
	//
	if (NULL == pActual)	
	{
		if (1L != cRequested)
		{
			return E_POINTER;
		}
	}

	// If we are at end of list return FALSE
	//
	if (m_lCurrentElem >= m_lNumUnks)
	{
		return S_FALSE;
	}

	// Return as many as we have left in list up to request count
	//
	while (m_lCurrentElem < m_lNumUnks && cRequested > 0)
	{
		ppUnk[cReturn] = m_pUnkList[m_lCurrentElem];

		if (NULL != ppUnk[cReturn])	// (should never be null)
		{
			ppUnk[cReturn]->AddRef();
		}

		// And move on to the next one
		//
		m_lCurrentElem++;
		cReturn++;
		cRequested--;
	}

	if (NULL != pActual)
	{
		*pActual = cReturn;
	}

	if (cReturn == maxcount)
	{
		return S_OK;
	}
	return S_FALSE;
}


////////////////////////////////////////////////////////////////
// CImpIEnumUnknown::Skip()
//
// Purpose:
//  Skips the next n elements in the enumeration.
//
// Parameters:
//  lNumSkip	ULONG number of elements to skip.
//
// Return Value:
//  HRESULT	-	S_OK if successful, S_FALSE if we could not 
//				skip the requested number.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIEnumUnknown::Skip(ULONG lNumSkip)
{
	if (((m_lCurrentElem + lNumSkip) >= m_lNumUnks) || NULL == m_pUnkList)
	{
		return S_FALSE;
	}

	m_lCurrentElem += lNumSkip;
	return S_OK;
}


////////////////////////////////////////////////////////////////
// CImpIEnumUnknown::Reset()
//
// Purpose:
//  Resets the current element index in the enumeration to zero.
//
// Parameters:
//  None
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIEnumUnknown::Reset(void)
{
	m_lCurrentElem = 0;
	return S_OK;
}


////////////////////////////////////////////////////////////////
// CImpIEnumUnknown::Clone()
//
// Purpose:
//  Returns another IEnumUnknown with the same state as ourselves.
//
// Parameters:
//  ppEnum		  LPENUMUNKNOWN * in which to return the
//				  new object.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIEnumUnknown::Clone(LPENUMUNKNOWN *ppEnum)
{
	CImpIEnumUnknown   *pNew;


	*ppEnum = NULL;

	//Create the clone
	//
	pNew = new CImpIEnumUnknown(m_pUnkOuter, m_lNumUnks, m_pUnkList, m_pIMalloc);

	if (NULL == pNew)
	{
		return E_OUTOFMEMORY;
	}

	pNew->AddRef();

	// Set the 'state' of the clone to match the state if this
	//
	pNew->m_lCurrentElem = m_lCurrentElem;

	*ppEnum=pNew;
	return S_OK;
}

⌨️ 快捷键说明

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