www.pudn.com > Ge_opc_Server_v1.rar > SERVER.CPP
// Server.cpp
//
// This file contains the implementation of
// the LHEpipeview Server Object for the OPC server.
//
// This implementation uses 'tear off' interfaces
// (I.e. the interfaces are separate from the object
// which supports only IUnknown)
//
//
// (c) COPYRIGHT 1996,1997 INTELLUTION INC.
// ALL RIGHTS RESERVED
//
// Original Author: Al Chisholm
//
// Modification Log:
// Vers Date By Notes
// ---- -------- --- -----
// 0.00 11/18/96 ACC
// 0.01 02/05/97 acc Fix memory leaks (see acc001)
// 0.90 04/08/97 ACC add async logic/UpdateData
//
//
#define WIN32_LEAN_AND_MEAN
#include "OPCLHEpipeview.h"
#include "OPCTHRD.h"
extern CRITICAL_SECTION CritSec;
/////////////////////////////////////////////////////////////////////////////
// Constructor /Destructor functions
//
///////////////////////////////////////
// OPCServer()
// Constructor for the OPC Server.
//
///////////////////////////////////////
LHEpipeviewServer::LHEpipeviewServer( LPUNKNOWN pOuter, void (*pfn)(void))
{
int j;
SYSTEMTIME SystemTime;
mRefCount = 0;
// Clear out 'tear-off' interface ptrs
// The interfaces will be created as needed in QueryInterface
//
m_pIServer = 0;
m_pISPG = 0;
m_pIBSAS = 0;
m_pIPF = 0;
GetSystemTime(&SystemTime); // Get current UTC Time
SystemTimeToFileTime(&SystemTime, &mLastUpdate); // and store it
m_pfnDestroy = pfn;
m_tid = 0;
// Clear out the 'Groups'
// This simple example only holds 10 groups
// A real implementation would use some sort
// of container or linked list
//
for (j=0; jRelease();
}
}
// Then delete any tear off interfaces
//
if(m_pIServer) delete m_pIServer;
// if(m_pISPG) delete m_pISPG;
// if(m_pIBSAS) delete m_pIBSAS;
if(m_pIPF) delete m_pIPF; //acc001
LeaveCriticalSection(&CritSec);
}
/////////////////////////////////////////////////////////////////////////////
// IUnknown functions
//
///////////////////////////////////////
// IUnknown::AddRef()
// Standard IUnknown implementation
//
///////////////////////////////////////
STDMETHODIMP_(ULONG) LHEpipeviewServer::AddRef( void)
{
return ++mRefCount;
}
///////////////////////////////////////
// IUnknown::Release()
// Standard IUnknown implementation
//
///////////////////////////////////////
STDMETHODIMP_(ULONG) LHEpipeviewServer::Release( void)
{
ULONG currentCount = --mRefCount;
// If no references left for this server
if ( currentCount == 0)
{
// Then delete this server.
//
if(m_pfnDestroy) (*m_pfnDestroy)(); // DLL or EXE can unload if last one
delete this;
}
return currentCount;
}
///////////////////////////////////////
// IUnknown::QueryInterface()
// Standard IUnknown implementation using
// 'tear off' interfaces
//
///////////////////////////////////////
STDMETHODIMP LHEpipeviewServer::QueryInterface( REFIID iid, LPVOID* ppInterface)
{
// check valid pointer
//
if ( ppInterface == NULL)
return E_INVALIDARG;
// default return is NULL in case of error
//
*ppInterface = NULL;
if ( iid == IID_IUnknown )
{
*ppInterface = (IUnknown*) this;
}
else if ( iid == IID_IOPCServer)
{
if(m_pIServer == 0) m_pIServer = new ILHEpipeviewServer(this);
*ppInterface = m_pIServer;
}
// else if (iid == IID_IOPCServerPublicGroups)
// {
// if(m_pISPG == 0) m_pISPG = new ILHEpipeviewOPCServerPublicGroups(this);
// *ppInterface = m_pISPG;
// }
// else if (iid == IID_IOPCBrowseServerAddressSpace)
// {
// if(m_pIBSAS == 0) m_pIBSAS = new ILHEpipeviewOPCBrowserServerAddressSpace(this);
// *ppInterface = m_pIBSAS;
// }
else if ((iid == IID_IPersistFile) || (iid == IID_IPersist))
{
if(m_pIPF == 0) m_pIPF = new ILHEpipeviewPF(this);
*ppInterface = m_pIPF;
}
else if ( iid == IID_IEnumUnknown)
{
// Note enumerators are special in that they are independent objects
// They are not just interfaces on an existing object
//
HRESULT hr;
ILHEpipeviewEnumUnknown *temp;
LPUNKNOWN * GroupList;
int GroupCount;
// Get a snapshot of the group list
// (Note this does NOT do AddRefs to the groups - but see ILHEpipeviewEnum below)
//
GetUnkList(OPC_ENUM_ALL_CONNECTIONS, &GroupList, &GroupCount);
// Create the Enumerator using the snapshot (which might be empty)
// Note that the enumerator constructor will AddRef
// all of the groups.
//
temp = new ILHEpipeviewEnumUnknown(this, GroupCount, GroupList, pIMalloc);
delete [] GroupList;
if ( temp == NULL)
return E_OUTOFMEMORY;
// Then QI for the interface ('temp') actually is the interface
// but QI is the 'proper' way to get it.
// Note QI will do an AddRef of the Enum which will also do
// an AddRef of the 'parent' - i.e. the 'this' pointer passed above.
//
hr = temp->QueryInterface( iid, ppInterface);
if ( FAILED( hr))
{
delete temp;
return hr;
}
// If all OK - return here
// Unlike most interfaces this one does NOT directly addref the server
// (since we created a new and independent object)
//
return S_OK;
}
if ( *ppInterface == NULL)
return E_NOINTERFACE;
AddRef();
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// Private (non-OPC) Utility Functions
//
///////////////////////////////////////
// LHEpipeviewServer::GetNameList()
// Create a list of all the group names
//
void LHEpipeviewServer::GetNameList( OPCENUMSCOPE scope, LPOLESTR**GroupList, int *GroupCount)
{
int j, count = 0;
LPOLESTR *mylist;
// Defaults...
*GroupList = NULL;
*GroupCount = 0;
// First pass - count private groups in use
//
for (j=0; jm_szName, NULL);
(*GroupCount)++;
}
}
break;
case OPC_ENUM_PUBLIC:
case OPC_ENUM_PUBLIC_CONNECTIONS:
default:
break;
}
}
///////////////////////////////////////
// LHEpipeviewServer::FreeNameList()
// Free a list of group names
//
void LHEpipeviewServer::FreeNameList( LPOLESTR*GroupList, int count)
{
int j;
if(!count) return;
for(j=0; jAsyncHelper(tics);
}
}
LeaveCriticalSection(&CritSec);
}
///////////////////////////////////////
// LHEpipeviewServer::GenerateTransactionID
//
void LHEpipeviewServer::GenerateTransaction(DWORD *pTID)
{
m_tid++;
if(m_tid == 0) m_tid++; // 0 is not a legal TID
*pTID = m_tid;
}