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

📄 impiopcserver.cpp

📁 基于Intellution开发包的开发的OPC服务器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
STDMETHODIMP CImpIOPCServer::AddGroup(LPCWSTR		szName, 
									  BOOL			bActive, 
									  DWORD			dwRequestedUpdateRate, 
									  OPCHANDLE		hClientGroup,
									  LONG			*pTimeBias, 
									  FLOAT			*pPercentDeadband, 
									  DWORD			dwLCID, 
									  OPCHANDLE		*phServerGroup,
									  DWORD			*pRevisedUpdateRate, 
									  REFIID		riid, 
									  LPUNKNOWN		*ppUnk)
{
	OPCHANDLE		OPCHandle;
	COPCDrvGroup	*pNewGroup	= NULL;
	HRESULT			hr;


	// Make sure that we didn't get any bad pointers
	//
	if ((NULL == szName) ||
		(NULL == ppUnk)  ||
		(NULL == phServerGroup))
	{
		return E_INVALIDARG;
	}

	// Default return in case of error
	//
	*ppUnk = NULL;

	// Generate Unique Name (WCHAR) if not supplied by caller.
	//	
	if (NULL == *szName)
	{
		CString		strGeneratedName;
		DWORD		dwNumGroups			= m_pParentServer->GetNumGroupHandles(),
					i					= 1;
		char		szNumGroups[15],
					*pszGeneratedName	= NULL;
		int			nLength				= 0;
		LPUNKNOWN	lpTest				= NULL;

		// Macro required for ATL string conversions
		//
		USES_CONVERSION;

		// We will try NumGroups + 1 different names. We SHOULD find one 
		// that isn't already configured.
		//
		while(i <= (dwNumGroups + 1))
		{
			strGeneratedName = g_strDefaultGeneratedGroupName;
			ltoa((dwNumGroups + i), szNumGroups, 10);
			strGeneratedName += szNumGroups;
			nLength	= strGeneratedName.GetLength();

			pszGeneratedName = strGeneratedName.GetBuffer(nLength+1);
			szName = A2W(pszGeneratedName);
			strGeneratedName.ReleaseBuffer();

			GetGroupByName(szName, IID_IUnknown, &lpTest);
			if(NULL == lpTest)
			{
				break;
			}
			i++;
		}
	}

	// Verify that the name provided is Unique
	//
	LPUNKNOWN	lpTest;
	GetGroupByName(szName, IID_IUnknown, &lpTest);
	if(lpTest)
	{
		lpTest->Release();
		return OPC_E_DUPLICATENAME;
	}

	// Create the new group and record our reference to it.
	//
	hr = m_pParentServer->GroupAlloc(&OPCHandle, &pNewGroup, this->m_pUnkOuter);
	if (FAILED(hr))
	{
		return E_OUTOFMEMORY;
	}
	pNewGroup->AddRef();

	// And request a 2nd interface for the caller
	//
	hr = pNewGroup->QueryInterface(riid, (LPVOID *)ppUnk);
	if(FAILED(hr))
	{
		// If error - delete group and return
		delete pNewGroup;
		return E_FAIL;
	}

	// Copy the data to the new group
	//
	pNewGroup->m_ServerGroupHandle	= OPCHandle;
	pNewGroup->m_szName				= WSTRClone(szName, NULL);
	pNewGroup->m_ClientGroupHandle	= hClientGroup;
	pNewGroup->m_LCID				= dwLCID;
	pNewGroup->SetActive(bActive);
	pNewGroup->SetUpdateRate(dwRequestedUpdateRate, pRevisedUpdateRate);
	if (pPercentDeadband)
	{
		pNewGroup->m_Deadband = *pPercentDeadband;
	}
	if(pTimeBias) 
	{
		pNewGroup->m_TimeBias = *pTimeBias;
	}

	// Add the new group to the map
	//
	m_pParentServer->GroupSet(pNewGroup);

	// Return handle of the new group to the caller
	//
	*phServerGroup = OPCHandle;

	// We now have a group in the server, so change the status to active
	//
	m_pParentServer->m_ServerState = OPC_STATUS_RUNNING;

	return S_OK;
}


////////////////////////////////////////////////////////////////
// CImpIOPCServer::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.
//
// Returns:
//	HRESULT	-	S_OK if the function succeeded
//			-	E_FAIL if the function failed. This will happen
//				if the name passed to us was not found in
//				the map.	
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCServer::GetGroupByName(LPCWSTR		szGroupName, 
											REFIID		riid, 
											LPUNKNOWN	*ppUnk)
{
	HRESULT			hr;
	OPCHANDLE		OPCHandle	= 0;
	COPCDrvGroup	*pGroup		= NULL;
	POSITION		posGroup	= m_pParentServer->GetFirstGroupPosition();
	int				nNumGroups	= m_pParentServer->GetNumGroupHandles();


	*ppUnk = 0;

	// Loop on the number of groups in the server until the name we are
	// looking for is found. If we don't find it, we will return E_FAIL.
	//
	for (int i = 0; i < nNumGroups; i++)
	{
		m_pParentServer->GetNextGroup(posGroup, OPCHandle, pGroup);

		if (!wcscmp(pGroup->m_szName, szGroupName))
		{
			// Then query for and return the requested interface
			//
			hr = pGroup->QueryInterface(riid, (LPVOID *)ppUnk);
			if(FAILED(hr))
			{
				// If error - return
				return E_FAIL;
			}
			return S_OK;
		}
	}

	return E_FAIL;
}


////////////////////////////////////////////////////////////////
// CImpIOPCServer::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.
//
// Returns:
//	HRESULT	-	S_OK if the function succeeded
//			-	E_FAIL if the function failed. This will happen
//				if the handle passed to us was not found in
//				the map.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCServer::RemoveGroup(OPCHANDLE	OPCHandle, 
										 BOOL		bForce)
{
	COPCDrvGroup	*pGroup	= NULL;


	// Lock the parent server object
	//
	m_pParentServer->Lock();

	// Make sure the passed ServerHandle is valid
	//
	if (FALSE == m_pParentServer->IsGroupValid(OPCHandle))
	{
		return E_FAIL;
	}

	// Remove it from the map. (This will perform a Release().)
	//
	m_pParentServer->GroupFree(OPCHandle, bForce);

	// If we have deleted the last groups in the server, then change the status to
	// not configured.
	//
	if (0 == m_pParentServer->GetNumGroupHandles())
	{
		m_pParentServer->m_ServerState = OPC_STATUS_NOCONFIG;
	}

	// Unlock the parent server
	//
	m_pParentServer->UnLock();
	return S_OK;
}


////////////////////////////////////////////////////////////////
// CImpIOPCServer::CreateGroupEnumerator()
//
// This function creates a string enumerator containing the
// group names for the server.
//
// Returns:
//	HRESULT	-	S_OK if the function succeeded.
//			-	E_FAIL if the function failed.
//			-	E_OUTOFMEMORY if a memory allocator failed.
//			-	S_FALSE if there is nothing to enumerate (in
//				the case that there are no groups).
//			-	E_INVALIDARG if a passed parameter is invalid.
//
////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIOPCServer::CreateGroupEnumerator(OPCENUMSCOPE		dwScope, 
												   REFIID			riid,
												   LPUNKNOWN		*ppUnk)
{
	if (NULL == ppUnk)
	{
		return E_INVALIDARG;
	}

	if (riid == IID_IEnumUnknown)
	{
		// Note this logic is also used in XXXServer::QueryInterface
		CImpIEnumUnknown	*pEnumUnknown;
		LPUNKNOWN			*pGroupList;
		int					nGroupCount;
		HRESULT				hr;


		// Get a snapshot of the group list 
		// (Note this does NOT do AddRefs to the groups - but see IXXXEnum below)
		//
		m_pParentServer->GetUnkList(dwScope, &pGroupList, &nGroupCount);

		// Informthe caller if there is nothing to enumerate
		//
		if (0 == nGroupCount)
		{
			*ppUnk = NULL;
			return S_FALSE;
		}

		// Create the Enumerator using the snapshot
		// Note that the enumerator will AddRef the server 
		// and also all of the groups.
		//
		pEnumUnknown = new CImpIEnumUnknown(m_pUnkOuter, nGroupCount, pGroupList, pIMalloc);
		m_pParentServer->FreeUnkList(pGroupList, nGroupCount);

		if (pEnumUnknown == NULL)
		{
			*ppUnk = NULL;
			return E_OUTOFMEMORY;
		}

		// Then QI for the interface ('pEnumString') 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 = pEnumUnknown->QueryInterface(riid, (LPVOID *)ppUnk);
		if (FAILED(hr))
		{
			*ppUnk = NULL;
			delete pEnumUnknown;
			return E_FAIL;
		}

		return S_OK;
	}
	else if (riid == IID_IEnumString)
	{
		CImpIEnumString		*pEnumString;
		LPOLESTR			*pGroupList;
		int					nGroupCount;
		HRESULT				hr;


		// Get a snapshot of the group list 
		//
		m_pParentServer->GetNameList(dwScope, &pGroupList, &nGroupCount);

		// Informthe caller if there is nothing to enumerate
		//
		if (0 == nGroupCount)
		{
			*ppUnk = NULL;
			return S_FALSE;
		}

		// Create the Enumerator using the snapshot
		// Note that the enumerator will AddRef the server 
		//
		pEnumString = new CImpIEnumString(m_pUnkOuter, nGroupCount, pGroupList, pIMalloc);
		m_pParentServer->FreeNameList(pGroupList, nGroupCount);

		if (pEnumString == NULL)
		{
			*ppUnk = NULL;
			return E_OUTOFMEMORY;
		}

		// Then QI for the interface ('pEnumString') 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 = pEnumString->QueryInterface(riid, (LPVOID *)ppUnk);
		if (FAILED(hr))
		{
			*ppUnk = NULL;
			delete pEnumString;
			return E_FAIL;
		}

		return S_OK;
	}

	// Unknow refiid, so return an error
	//
	*ppUnk = NULL;
	return E_INVALIDARG;
}

⌨️ 快捷键说明

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