?? impiopcasyncio.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 + -