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

📄 impiopcasyncio.cpp

📁 基于Intellution开发包的开发的OPC服务器
💻 CPP
字号:
// ImIOPCAsyncIO.cpp
//
//  This file contains the implementation of 
//  the IOPCASyncIO interface for groups in the OPC server.
//
//	(c) COPYRIGHT 1996-1998, INTELLUTION INC.
// ALL RIGHTS RESERVED
//
//
//	Functions defined in this module:
//
//			CImpIOPCAsyncIO::CImpIOPCAsyncIO()
//			CImpIOPCAsyncIO::~CImpIOPCAsyncIO()
//			CImpIOPCAsyncIO::AddRef()
//			CImpIOPCAsyncIO::Release()
//			CImpIOPCAsyncIO::QueryInterface()
//			CImpIOPCAsyncIO::Read()
//			CImpIOPCAsyncIO::Write()
//			CImpIOPCAsyncIO::Refresh()
//			CImpIOPCAsyncIO::Cancel()
//
//
//
// 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.
//
//

#include "OpcStdAfx.h"

#include "OPC.h"
#include "OPCError.h"

#define WIN32_LEAN_AND_MEAN


/////////////////////////////////////////////////////////////////////////////
// Constructor /Destructor functions
//

////////////////////////////////////////////////////////////////
// CImpIOPCAsyncIO()
//   Constructor for this Interface
//
////////////////////////////////////////////////////////////////
CImpIOPCAsyncIO::CImpIOPCAsyncIO(LPUNKNOWN pUnkOuter)
{
	m_pUnkOuter = pUnkOuter;
	m_pParentGroup = (COPCDrvGroup *)pUnkOuter;
}


////////////////////////////////////////////////////////////////
// ~CImpIOPCAsyncIO()
//   Destructor for this Interface
//
////////////////////////////////////////////////////////////////
CImpIOPCAsyncIO::~CImpIOPCAsyncIO( void)
{
	m_pParentGroup->m_pCImpIAsyncIO = NULL;
}


/////////////////////////////////////////////////////////////////////////////
// IUnknown functions Delegate to Parent
//

////////////////////////////////////////////////////////////////
// AddRef()
//
////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIOPCAsyncIO::AddRef(void)
{
	return m_pUnkOuter->AddRef();
}


////////////////////////////////////////////////////////////////
// Release()
//
////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIOPCAsyncIO::Release(void)
{
	return m_pUnkOuter->Release();
}


////////////////////////////////////////////////////////////////
// QueryInterface()
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCAsyncIO::QueryInterface(REFIID		iid, 
											 LPVOID		*ppInterface)
{
	return m_pUnkOuter->QueryInterface(iid, ppInterface);
}


/////////////////////////////////////////////////////////////////////////////
// CImpIOPCAsyncIO (IOPCAsyncIO) interface functions
//


////////////////////////////////////////////////////////////////
// Read()
//
// Queue up an Async read.
// 
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCAsyncIO::Read(DWORD			dwConnection, 
								   OPCDATASOURCE	dwSource,
								   DWORD			dwNumItems, 
								   OPCHANDLE		*phServer,
								   DWORD			*pTransactionID, 
								   HRESULT			**ppErrors)
{
	COPCDrvServer		*pParentServer	= m_pParentGroup->m_pParentServer;
	BOOL				bReject			= FALSE;
	HRESULT				*phResults		= NULL;
	COPCDrvAsyncTrans	*pTransaction	= NULL;


	// Make sure that we didn't get any bad pointers
	//
	if ((0 == dwNumItems) || (NULL == phServer) || (NULL == pTransactionID) ||
		(NULL == ppErrors))
	{
		return E_INVALIDARG;
	}

	// Make sure the client has registered for async callbacks
	//
	if ((!m_pParentGroup->m_pCImpIDataObject->IsAdvisedForDataTime()) && 
		(!m_pParentGroup->m_pCImpIDataObject->IsAdvisedForData()))
	{
		*pTransactionID = NULL;
		*ppErrors		= NULL;
		return CONNECT_E_NOCONNECTION;
	}

	// Initialize OUT parameters to NULL
	//
	*pTransactionID	= NULL;
	*ppErrors		= NULL;

	// Alloc memory for returned error list
	// and the stored handle list (to be returned later in the callback)
	//
	phResults = *ppErrors = (HRESULT *)pIMalloc->Alloc(dwNumItems * sizeof(HRESULT));
	if(NULL == phResults)
	{
		return E_OUTOFMEMORY;
	}

	// Lock the parent group so no one else removes or adds any items
	//
	m_pParentGroup->Lock();

	// First, validate ALL of the handles
	//
	for (DWORD j = 0; j < dwNumItems; j++)
	{
		if (!m_pParentGroup->IsItemValid(phServer[j]))
		{
			phResults[j] = OPC_E_INVALIDHANDLE;
			bReject = TRUE;
			continue;
		}

		phResults[j] = S_OK;
	}

	// If any handles are bad then we are finished
	//
	if (bReject)
	{
		m_pParentGroup->UnLock();
		return OPC_E_INVALIDHANDLE;
	}

	// If all handles are good, create and initialize a new transaction
	//
	pTransaction = new COPCDrvAsyncTrans(m_pParentGroup);
	if (NULL == pTransaction)
	{
		pIMalloc->Free(phResults);
		m_pParentGroup->UnLock();
		return E_OUTOFMEMORY;
	}

	if (FAILED(pTransaction->Init(TRANS_READ, dwSource, dwNumItems, phServer)))
	{
		pIMalloc->Free(phResults);
		delete pTransaction;
		m_pParentGroup->UnLock();
		return E_FAIL;
	}

	// Get the transaction ID for the caller and add the read to the queue
	//
	*pTransactionID = pTransaction->GetTransactionID();
	pTransaction->AddToQueue();

	// Unlock the parent group object
	//
	m_pParentGroup->UnLock();

	return S_OK;
}


////////////////////////////////////////////////////////////////
// Write()
//
// Queue up an Async Write.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCAsyncIO::Write(DWORD			dwConnection, 
									DWORD			dwNumItems, 
									OPCHANDLE		*phServer, 
									VARIANT			*pItemValues, 
									DWORD			*pTransactionID, 
									HRESULT			**ppErrors)
{
	COPCDrvServer		*pParentServer	= m_pParentGroup->m_pParentServer;
	unsigned int		j;
	BOOL				bReject			= FALSE;
	HRESULT				*phResults		= NULL;
	COPCDrvAsyncTrans	*pTransaction	= NULL;


	// Sanity Checks
	//
	if ((0 == dwNumItems) || (NULL == phServer) || (NULL == pTransactionID) ||
		(NULL == pItemValues) || (NULL == ppErrors))
	{
		return E_INVALIDARG;
	}

	// Make sure the client has registered for async callbacks
	//
	if (!m_pParentGroup->m_pCImpIDataObject->IsAdvisedForWriteComplete())
	{
		*pTransactionID = NULL;
		*ppErrors		= NULL;
		return CONNECT_E_NOCONNECTION;
	}

	// Make sure the client has registered for async callbacks
	//
	if (!m_pParentGroup->m_pCImpIDataObject->IsAdvisedForWriteComplete())
	{
		*pTransactionID = NULL;
		*ppErrors		= NULL;
		return CONNECT_E_NOCONNECTION;
	}

	// Initialize OUT parameters to NULL
	//
	*pTransactionID	= NULL;
	*ppErrors		= NULL;

	// Alloc memory for returned error list
	// and the stored handle list (to be returned later in the callback)
	//
	phResults = *ppErrors = (HRESULT *)pIMalloc->Alloc(dwNumItems * sizeof(HRESULT));
	if(NULL == phResults)
	{
		return E_OUTOFMEMORY;
	}

	// Lock the parent group so no one else removes or adds any items
	//
	m_pParentGroup->Lock();

	// First, validate ALL of the handles
	//
	for (j = 0; j < dwNumItems; j++)
	{
		if (!m_pParentGroup->IsItemValid(phServer[j]))
		{
			phResults[j] = OPC_E_INVALIDHANDLE;
			bReject = TRUE;
			continue;
		}

		phResults[j] = S_OK;
	}

	// If any handles are bad then we are finished
	//
	if (bReject)
	{
		m_pParentGroup->UnLock();
		return OPC_E_INVALIDHANDLE;
	}

	// If all handles are good, create and initialize a new transaction
	//
	pTransaction = new COPCDrvAsyncTrans(m_pParentGroup);
	if (NULL == pTransaction)
	{
		pIMalloc->Free(phResults);
		m_pParentGroup->UnLock();
		return E_OUTOFMEMORY;
	}

	if (FAILED(pTransaction->Init(TRANS_WRITE, OPC_DS_CACHE, dwNumItems, phServer, pItemValues)))
	{
		pIMalloc->Free(phResults);
		delete pTransaction;
		m_pParentGroup->UnLock();
		return E_FAIL;
	}

	// Get the transaction ID for the caller and add the write to the queue
	//
	*pTransactionID = pTransaction->GetTransactionID();
	pTransaction->AddToQueue();

	m_pParentGroup->UnLock();

	return S_OK;
}


////////////////////////////////////////////////////////////////
// Refresh()
//
// Queue up an Async refresh 
// (which is a cross between async read and OnDataChange).
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCAsyncIO::Refresh(DWORD				dwConnection, 
									  OPCDATASOURCE		dwSource,
									  DWORD				*pTransactionID)
{
	COPCDrvItem		*pItem;
	POSITION		posItem;
	OPCHANDLE		OPCHandle;
	int				nNumActiveItems	= 0;
	DWORD			dwNumItems		= 0;
	OPCHANDLE		*pHandleList	= NULL;
	HRESULT			hr,
					*pErrors		= NULL;


	// Make sure the client has registered for async callbacks
	//
	if ((!m_pParentGroup->m_pCImpIDataObject->IsAdvisedForDataTime()) && 
		(!m_pParentGroup->m_pCImpIDataObject->IsAdvisedForData()))
	{
		*pTransactionID = NULL;
		return CONNECT_E_NOCONNECTION;
	}

	// Initialize OUT parameters to NULL
	//
	*pTransactionID = NULL;

	// Lock the parent group so nothing changes
	//
	m_pParentGroup->Lock();

	posItem		= m_pParentGroup->GetFirstItemPosition();
	dwNumItems	= m_pParentGroup->GetNumItemHandles();

	// Allocate the memory for the handle list
	//
	pHandleList = new OPCHANDLE [dwNumItems];
	if(NULL == pHandleList) 
	{
		m_pParentGroup->UnLock();
		return E_OUTOFMEMORY;
	}

	// Count active items in group
	//
	if (m_pParentGroup->m_bActive)
	{
		for (DWORD j = 0; j < dwNumItems; j++)
		{
			m_pParentGroup->GetNextItem(posItem, OPCHandle, pItem);

			// If item is in use
			//
			if (pItem->m_bActive)
			{
				pHandleList[j] = OPCHandle;
				nNumActiveItems++;
			}
		}
	}

	m_pParentGroup->UnLock();

	// If nothing active, return FAIL (per spec)
	//
	if (0 == nNumActiveItems)
	{
		delete [] pHandleList;
		return E_FAIL;
	}

	// We are just going to do a read for all active items in the list
	//
	hr = Read(dwConnection, 
			  dwSource,
			  dwNumItems, 
			  pHandleList,
			  pTransactionID,
			  &pErrors);

	// Free the error list because we don't need it
	//
	if (pErrors)
	{
		CoTaskMemFree(pErrors);
	}
	if (pHandleList)
	{
		delete [] pHandleList;
	}

	if (FAILED(hr))
	{
		return E_FAIL;
	}
	return S_OK;
}


////////////////////////////////////////////////////////////////
// Cancel()
//
// This function cancels a pending asynch transaction.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCAsyncIO::Cancel(DWORD		dwTransactionID)
{
	COPCDrvAsyncTrans	*pTrans		= NULL;
	POSITION			posTrans	= NULL;
	HRESULT				hr			= E_FAIL;


	// Lock the parent group because the asynch transaction may
	// already be in progress.
	//
	m_pParentGroup->Lock();

	// search for this transaction in the queues
	//
	if(m_pParentGroup->m_AsyncReadQueue.GetCount() > 0)
	{
		posTrans = m_pParentGroup->m_AsyncReadQueue.GetHeadPosition();
		while (posTrans)
		{
			pTrans = (COPCDrvAsyncTrans *)m_pParentGroup->m_AsyncReadQueue.GetNext(posTrans);
			if (pTrans->GetTransactionID() == dwTransactionID)
			{
				pTrans->Cancel();
				hr = S_OK;
				break;
			}
		}
	}
	if ((m_pParentGroup->m_AsyncWriteQueue.GetCount() > 0) && (S_OK != hr))
	{
		posTrans = m_pParentGroup->m_AsyncWriteQueue.GetHeadPosition();
		while (posTrans)
		{
			pTrans = (COPCDrvAsyncTrans *)m_pParentGroup->m_AsyncWriteQueue.GetNext(posTrans);
			if (pTrans->GetTransactionID() == dwTransactionID)
			{
				pTrans->Cancel();
				hr = S_OK;
				break;
			}
		}
	}

	// Unlock the parent group.
	//
	m_pParentGroup->UnLock();
	return hr;
}

⌨️ 快捷键说明

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