www.pudn.com > GEOPC_modified_2005621145656299.rar > SERVER.CPP, change:2005-04-08,size:11912b


// Server.cpp 
// 
//  This file contains the implementation of  
//  the XXX Server Object for the OPC Sample 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 "implconnect.h" 
#include "opccomn_i.c" 
#include "OPCXXX.h" 
#include "OPCTHRD.h" 
 
extern CRITICAL_SECTION	CritSec; 
 
///////////////////////////////////////////////////////////////////////////// 
// Constructor /Destructor functions 
// 
 
/////////////////////////////////////// 
// OPCServer() 
//   Constructor for the OPC Sample Server. 
// 
/////////////////////////////////////// 
XXXServer::XXXServer( 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; 
	m_pCImpIConnPointContainer=NULL; 
	m_pCImpIConnPoint=NULL; 
 
	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; j<N_GRPS; j++) 
	{ 
		m_groups[j].inuse = 0; 
		m_groups[j].pGroup = NULL; 
	} 
 
	// Finally, plug this server into the Async helper 
	// 
	m_Slot = 0; 
	FindServerSlot(&m_Slot, this); 
	//zzz need error check! 
} 
 
 
 
/////////////////////////////////////// 
// ~XXXServer() 
//   Destructor for the OPC Sample Server. 
// 
/////////////////////////////////////// 
XXXServer::~XXXServer( void) 
{ 
	int	j; 
 
	// Enter critical section whenever deleting anything 
	// 
	EnterCriticalSection(&CritSec); 
 
	// First, turn off background processing	//acc003 
	// 
	if(m_Slot)ClearServerSlot(m_Slot); 
 
	// If necessary free any memory associated with the GROUPS 
	// (e.g. CStrings) 
	// 
	for (j=0; j<N_GRPS; j++) 
	{ 
		// Your code here... 
		// 
		if(m_groups[j].inuse) 
		{ 
			m_groups[j].pGroup->Release(); 
		} 
	} 
 
	// 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) XXXServer::AddRef( void) 
{ 
	return ++mRefCount; 
} 
 
 
 
/////////////////////////////////////// 
// IUnknown::Release() 
//   Standard IUnknown implementation 
// 
/////////////////////////////////////// 
STDMETHODIMP_(ULONG) XXXServer::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 XXXServer::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 IXXXServer(this); 
		*ppInterface = m_pIServer; 
	} 
//	else if (iid == IID_IOPCServerPublicGroups) 
//	{ 
	//	if(m_pISPG == 0) m_pISPG = new IXXXOPCServerPublicGroups(this); 
//		*ppInterface = m_pISPG; 
//	} 
	else if (iid == IID_IConnectionPointContainer) 
	{ 
		 
		if (NULL == m_pCImpIConnPoint) 
		{ 
			m_pCImpIConnPoint = new CImpIConnectionPoint(this, IID_IOPCShutdown); 
			if (NULL == m_pCImpIConnPoint) 
			{ 
				return E_OUTOFMEMORY; 
			} 
		//	OPC_TRACE("COPCDrvServer::QueryInterface() Created new 'CImpIConnectionPoint(this, IID_IOPCShutdown)'" ); 
		} 
 
		// Create the connection point container 
		if (NULL == m_pCImpIConnPointContainer) 
		{ 
			m_pCImpIConnPointContainer = new CImpIConnectionPointContainer(this, &m_pCImpIConnPoint, 1); 
			if (NULL == m_pCImpIConnPointContainer) 
			{ 
				return E_OUTOFMEMORY; 
			} 
			//	OPC_TRACE("COPCDrvServer::QueryInterface() Created new 'CImpIConnectionPointContainer(this, &m_pCImpIConnPoint, 1)'" ); 
		} 
 
		// Set it up 
		*ppInterface = static_cast<IConnectionPointContainer *>(m_pCImpIConnPointContainer); 
 
		//szIntf = "IConnectionPointContainer"; 
	} 
	else if (iid == IID_IOPCBrowseServerAddressSpace) 
	{ 
		if(m_pIBSAS == 0) m_pIBSAS = new IXXXBSAS(this,pIMalloc); 
		*ppInterface = m_pIBSAS; 
	} 
	else if ((iid == IID_IPersistFile) || (iid == IID_IPersist)) 
	{ 
		if(m_pIPF == 0) m_pIPF = new IXXXPF(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; 
		IXXXEnumUnknown *temp; 
		LPUNKNOWN * GroupList; 
		int	GroupCount; 
 
		// Get a snapshot of the group list  
		// (Note this does NOT do AddRefs to the groups - but see IXXXEnum 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 IXXXEnumUnknown(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 
// 
 
 
/////////////////////////////////////// 
// XXXServer::GetNameList() 
// Create a list of all the group names 
// 
void XXXServer::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; j<N_GRPS; j++) 
	{ 
		if(m_groups[j].inuse) count++; 
	} 
	if(!count)  
	{ 
		return; 
	} 
 
	// Second pass - figure out what to return and do it 
	// 
	switch(scope) 
	{ 
	case OPC_ENUM_PRIVATE_CONNECTIONS: 
	case OPC_ENUM_PRIVATE: 
	case OPC_ENUM_ALL_CONNECTIONS: 
	case OPC_ENUM_ALL: 
		*GroupList = mylist = new LPOLESTR[count];	// Caller must free this! 
		if (*mylist == NULL) 
		{ 
			return; 
		} 
		for (j=0; j<N_GRPS; j++) 
		{ 
			if(m_groups[j].inuse)  
			{ 
				// Note that the string is cloned to keep the enumerator 'stable' 
				mylist[*GroupCount] = WSTRClone(m_groups[j].pGroup->m_szName, NULL); 
				(*GroupCount)++; 
			} 
		} 
		break; 
 
	case OPC_ENUM_PUBLIC: 
	case OPC_ENUM_PUBLIC_CONNECTIONS: 
	default: 
		break; 
	} 
} 
 
/////////////////////////////////////// 
// XXXServer::FreeNameList() 
// Free a list of group names 
// 
void XXXServer::FreeNameList( LPOLESTR*GroupList, int count) 
{ 
	int j; 
	 
	if(!count) return; 
 
	for(j=0; j<count; j++) 
	{ 
		delete [] GroupList[j]; 
	} 
	delete [] GroupList; 
} 
 
/////////////////////////////////////// 
// XXXServer::GetUnkList() 
// Create a list of all the group Unknown Pointers 
// Note that we do NOT AddRef the pointers here - the caller must do that 
// 
void XXXServer::GetUnkList( OPCENUMSCOPE scope, LPUNKNOWN ** GroupList, int *GroupCount) 
{ 
	int	j, count = 0; 
	LPUNKNOWN *mylist; 
 
	// Defaults... 
	*GroupList = NULL; 
	*GroupCount = 0; 
 
	// First pass - count private groups in use 
	// 
	for (j=0; j<N_GRPS; j++) 
	{ 
		if(m_groups[j].inuse) count++; 
	} 
	if(!count)  
	{ 
		return; 
	} 
 
	// Second pass - figure out what to return and do it 
	// 
	switch(scope) 
	{ 
	//zzz this code is supposed to look at the reference counts but does not 
	case OPC_ENUM_PRIVATE_CONNECTIONS: 
	case OPC_ENUM_PRIVATE: 
	case OPC_ENUM_ALL_CONNECTIONS: 
	case OPC_ENUM_ALL: 
		*GroupList = mylist = new LPUNKNOWN[count]; 
		if (*mylist == NULL) 
		{ 
			return; 
		} 
		for (j=0; j<N_GRPS; j++) 
		{ 
			if(m_groups[j].inuse)  
			{ 
				mylist[*GroupCount] = (LPUNKNOWN)(m_groups[j].pGroup); 
				(*GroupCount)++; 
			} 
		} 
		break; 
 
	case OPC_ENUM_PUBLIC: 
	case OPC_ENUM_PUBLIC_CONNECTIONS: 
	default: 
		break; 
	} 
} 
 
/////////////////////////////////////// 
// XXXServer::FreeUnkList() 
// Free a list of group pointers 
// Note that since GetUnkList did not addref, we do not release 
// 
void XXXServer::FreeUnkList( LPUNKNOWN*GroupList, int count) 
{ 
	 
	if(!count) return; 
 
	delete [] GroupList; 
} 
 
/////////////////////////////////////// 
// XXXServer::UpdateData 
// 
// Handle any async operations 
// This includes Data Refresh 
//  
// 
void XXXServer::UpdateData(DWORD tics) 
{ 
	int j; 
 
	EnterCriticalSection(&CritSec); 
 
	// For each possible group in server... 
	// 
	for(j=0; j<N_GRPS; j++) 
	{ 
		// if group in this slot  
		// 
		if(m_groups[j].inuse)  
		{ 
			XXXGroup *group; 
 
			// get local group pointer (XXXGroup) 
			// and handle any Asnyc events for the group 
			// 
			group = m_groups[j].pGroup; 
 
			group->AsyncHelper(tics); 
		} 
	} 
 
	LeaveCriticalSection(&CritSec); 
} 
 
 
/////////////////////////////////////// 
// XXXServer::GenerateTransactionID 
// 
void XXXServer::GenerateTransaction(DWORD *pTID) 
{ 
	m_tid++; 
	if(m_tid == 0) m_tid++;	// 0 is not a legal TID 
	*pTID = m_tid; 
} 
 
static LPOLESTR tags[] =  
{ 
	L"7UD22Q0A01", 
	L"FIC102", 
	L"FIC103", 
	L"FIC104", 
	L"FIC105", 
	L"FIC106", 
	L"FIC107", 
	L"FIC108", 
	L"FIC109", 
}; 
void XXXServer::GetAddressList(  
	OPCBROWSETYPE dwBrowseFilterType, 
	LPCWSTR szFilterCriteria, 
	VARTYPE vtDataTypeFilter, 
	DWORD dwAccessRightsFilter, 
	LPOLESTR**AddressList,  
	int *AddressCount) 
{ 
	int	j, count = 9; 
	LPOLESTR *mylist; 
 
	// Defaults... 
	*AddressList = NULL; 
	*AddressCount = 0; 
 
	*AddressList = mylist = new LPOLESTR[count];	// Caller must free this! 
	if (*mylist == NULL) 
	{ 
		return; 
	} 
	for (j=0; j<count; j++) 
	{ 
		// Note that the string is cloned to keep the enumerator 'stable' 
		mylist[*AddressCount] = WSTRClone( tags[j], NULL); 
	} 
	*AddressCount = count; 
} 
 
/////////////////////////////////////// 
// XXXServer::FreeAddressList() 
// Free a list of Item names 
// 
void XXXServer::FreeAddressList( LPOLESTR*AddressList, int count) 
{ 
	int j; 
	 
	if(!count) return; 
 
	for(j=0; j<count; j++) 
	{ 
		delete [] AddressList[j]; 
	} 
	delete [] AddressList; 
}