www.pudn.com > Ge_opc_Server_v1.rar > I_SERVER.CPP
// I_Server.cpp
//
// This file contains the implementation of
// the IOPCServer interface for the LHEpipeview server.
//
//
// (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
// 12/06/96 acc add GetGroupByName
// 0.02 05/05/97 acc (acc002) generate unique group name
// if none provided by caller.
// and verify that caller provided name is locally unique
//
//
#define WIN32_LEAN_AND_MEAN
#include "OPCLHEpipeview.h"
#include "OPCERROR.h"
extern CRITICAL_SECTION CritSec;
/////////////////////////////////////////////////////////////////////////////
// Constructor /Destructor functions
//
///////////////////////////////////////
// ILHEpipeviewServer()
// Constructor for this Interface
//
///////////////////////////////////////
ILHEpipeviewServer::ILHEpipeviewServer( LPUNKNOWN parent )
{
m_Parent = (LHEpipeviewServer *)parent;
}
///////////////////////////////////////
// ~ILHEpipeviewServer()
// Destructor for this Interface
//
///////////////////////////////////////
ILHEpipeviewServer::~ILHEpipeviewServer( void)
{
}
/////////////////////////////////////////////////////////////////////////////
// IUnknown functions Delegate to Parent
//
STDMETHODIMP_(ULONG) ILHEpipeviewServer::AddRef( void)
{
return m_Parent->AddRef();
}
STDMETHODIMP_(ULONG) ILHEpipeviewServer::Release( void)
{
return m_Parent->Release();
}
STDMETHODIMP ILHEpipeviewServer::QueryInterface( REFIID iid, LPVOID* ppInterface)
{
return m_Parent->QueryInterface(iid, ppInterface);
}
/////////////////////////////////////////////////////////////////////////////
// ILHEpipeviewServer (IOPCServer) interface functions
//
static WCHAR VendorInfo[] = L"中油龙慧自动化工程有限公司";
///////////////////////////////////////
// ILHEpipeviewServer::GetStatus()
// This function fills in the OPCSERVERSTATUS structure that was passed in.
///////////////////////////////////////
STDMETHODIMP ILHEpipeviewServer::GetStatus( OPCSERVERSTATUS** ppServerStatus)
{
OPCSERVERSTATUS* pServerStatus;
if ( ppServerStatus == NULL)
return E_INVALIDARG;
// allocate some memory for the struct
pServerStatus = (OPCSERVERSTATUS*) pIMalloc->Alloc( sizeof(OPCSERVERSTATUS) );
if(pServerStatus)
{
// and for the serverinfo string
pServerStatus->szVendorInfo = WSTRClone( VendorInfo, pIMalloc);
pServerStatus->ftStartTime = serverStartTime;
CoFileTimeNow( &pServerStatus->ftCurrentTime);
pServerStatus->ftLastUpdateTime = m_Parent->mLastUpdate;
pServerStatus->dwServerState = OPC_STATUS_RUNNING;
pServerStatus->dwGroupCount = 0;
pServerStatus->dwBandWidth = 0;
pServerStatus->wMajorVersion = 0;
pServerStatus->wMinorVersion = 0;
pServerStatus->wBuildNumber = 0;
pServerStatus->wReserved = 42;
}
else
{
// else the struct alloc failed
}
// return the result (if any) and the error
*ppServerStatus = pServerStatus;
if(pServerStatus) return S_OK;
return E_OUTOFMEMORY;
}
///////////////////////////////////////
// ILHEpipeviewServer::GetErrorString()
// For server specific error codes we need to return a user displayable string
// in the user's language.
// The easiest way to do this is to put the strings in the RC file and use LoadString
//
///////////////////////////////////////
STDMETHODIMP ILHEpipeviewServer::GetErrorString( HRESULT hr, LCID locale, LPWSTR *ppString)
{
static WCHAR * test = L"Test Error String...";
// A real server would obtain the string from a resource file
// In any case however we need to allocate some memory to return
// to the caller.
//
*ppString = WSTRClone( test, pIMalloc);
return S_OK;
}
///////////////////////////////////////
// ILHEpipeviewServer::AddGroup()
// This function creates a new group of the specified name on this server.
// Note TimeBias, Deadband and LCID are not implemented
///////////////////////////////////////
STDMETHODIMP ILHEpipeviewServer::AddGroup(
LPCWSTR szName,
BOOL bActive,
DWORD dwRequestedUpdateRate,
OPCHANDLE hClientGroup,
LONG *pTimeBias,
FLOAT *pPercentDeadband,
DWORD dwLCID,
OPCHANDLE *phServerGroup,
DWORD *pRevisedUpdateRate,
REFIID riid,
LPUNKNOWN *ppUnk
)
{
int j;
LHEpipeviewGroup *newgroup;
LHEpipeviewServer &s = *m_Parent;
HRESULT r1;
char nbuf[10];
WCHAR Wnbuf[20];
// Default return in case of error
//
*ppUnk = 0;
// Tentatively find a place to put the group
//
for(j=0; j= N_GRPS)
return E_OUTOFMEMORY;
// Generate Unique Name (WCHAR) if not supplied by caller acc002
// Note the algorithm below is a somewhat 'weak' example
//
if(!szName)
{
char *p = itoa(j, nbuf, 10);
WCHAR *s = Wnbuf;
while(*p)
{
*s = *p; // convert SBCS to WCHAR
s++;p++;
}
szName = Wnbuf;
}
// Verify that the name provided is Unique acc002
//
LPUNKNOWN test;
GetGroupByName(szName, IID_IUnknown, &test);
if(test)
{
test->Release();
return OPC_E_DUPLICATE_NAME;
}
// Create the group (returns IUnknown)
// and do an 'AddRef' since we will hold this IUnknown
// in the Server
//
newgroup = new LHEpipeviewGroup(m_Parent);
if(newgroup == NULL)
{
return E_OUTOFMEMORY;
}
newgroup->AddRef();
// And request a 2nd interface for the caller
//
r1 = newgroup->QueryInterface(riid, (LPVOID*) ppUnk);
if(FAILED(r1))
{
// If error - delete group and return
delete newgroup;
return r1;
}
// If OK then Record the group in the server for future use
//
s.m_groups[j].inuse = 1;
s.m_groups[j].pGroup = newgroup;
newgroup->m_ServerGroupHandle = j;
newgroup->m_ClientGroupHandle = hClientGroup;
newgroup->m_dwRevisedRate = dwRequestedUpdateRate;
newgroup->m_bActive = bActive;
newgroup->m_szName = WSTRClone(szName, NULL);
newgroup->m_Deadband = *pPercentDeadband;
newgroup->m_LCID = dwLCID;
if(pTimeBias)
newgroup->m_TimeBias = *pTimeBias;
else
newgroup->m_TimeBias = 0L;
// Return handle and updaterate to the caller
//
*phServerGroup = j;
if(pRevisedUpdateRate) *pRevisedUpdateRate = newgroup->m_dwRevisedRate;
return S_OK;
}
///////////////////////////////////////
// ILHEpipeviewServer::GetGroupByName()
// This function scans the set of groups known to this OPC server and returns a pointer to the
// IOPCGroup interface for the specified group.
///////////////////////////////////////
STDMETHODIMP ILHEpipeviewServer::GetGroupByName( LPCWSTR szGroupName,
REFIID riid, LPUNKNOWN *ppUnk)
{
int j;
LHEpipeviewGroup *group;
LHEpipeviewServer &s = *m_Parent;
HRESULT r1;
*ppUnk = 0;
// For each 'slot' in this server...
//
for(j=0; jm_szName, szGroupName) == 0)
{
// Then query for and return the requested interface
//
group = s.m_groups[j].pGroup;
r1 = group->QueryInterface(riid, (LPVOID*) ppUnk);
if(FAILED(r1))
{
// If error - return
return r1;
}
return S_OK;
}
}
return E_FAIL;
}
///////////////////////////////////////
// ILHEpipeviewServer::RemoveGroup()
// This function removes the specified group from the server.
// Note that the group doesn't
// go away until the last reference to it is removed.
// bForce is not currently implemented
//
///////////////////////////////////////
STDMETHODIMP ILHEpipeviewServer::RemoveGroup( OPCHANDLE groupHandleID, BOOL bForce)
{
int j;
LHEpipeviewServer &s = *m_Parent;
LHEpipeviewGroup *group;
// find the group with the passed ServerHandle
//
for(j=0; jm_ServerGroupHandle))
break;
}
if(j >= N_GRPS)
return E_FAIL;
group = s.m_groups[j].pGroup;
// release this reference to it
// (which will delete it if the reference goes to 0)
// and mark the slot unused
//
EnterCriticalSection(&CritSec);
group->Release();
s.m_groups[j].inuse = 0;
LeaveCriticalSection(&CritSec);
return S_OK;
}
///////////////////////////////////////
// ILHEpipeviewServer::CreateGroupEnumerator()
//
///////////////////////////////////////
STDMETHODIMP ILHEpipeviewServer::CreateGroupEnumerator(
OPCENUMSCOPE dwScope,
REFIID riid,
LPUNKNOWN *ppUnk
)
{
if ( riid == IID_IEnumUnknown)
{
// Note this logic is also used in LHEpipeviewServer::QueryInterface
ILHEpipeviewEnumUnknown *temp;
LPUNKNOWN * GroupList;
int GroupCount;
HRESULT hr;
// Get a snapshot of the group list
// (Note this does NOT do AddRefs to the groups - but see ILHEpipeviewEnum below)
//
m_Parent->GetUnkList( dwScope, &GroupList, &GroupCount);
// Create the Enumerator using the snapshot
// Note that the enumerator will AddRef the server
// and also all of the groups.
//
temp = new ILHEpipeviewEnumUnknown(m_Parent, GroupCount, GroupList, pIMalloc);
m_Parent->FreeUnkList(GroupList, GroupCount);
// 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( riid, (LPVOID*)ppUnk);
if ( FAILED( hr))
{
delete temp;
return hr;
}
return S_OK;
}
else if ( riid == IID_IEnumString)
{
ILHEpipeviewEnumString *temp;
LPOLESTR * GroupList;
int GroupCount;
HRESULT hr;
// Get a snapshot of the group list
//
m_Parent->GetNameList( dwScope, &GroupList, &GroupCount);
// Create the Enumerator using the snapshot
// Note that the enumerator will AddRef the server
//
temp = new ILHEpipeviewEnumString(m_Parent, GroupCount, GroupList, pIMalloc);
m_Parent->FreeNameList(GroupList, GroupCount);
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( riid, (LPVOID*)ppUnk);
if ( FAILED( hr))
{
delete temp;
return hr;
}
return S_OK;
}
return E_INVALIDARG;
}