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

📄 advisesink.cpp

📁 用VC编写的OPC 客户端程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				case VT_R8	| VT_ARRAY:
					{
					// Read array parameters:
					SAFEARRAY sa;
					DWORD cdwElements;
					pStream->Read (&sa, sizeof (SAFEARRAY), NULL);

					// 2-D array:
					if (sa.cDims != 1)
						{
						// Read array parameters for second dimension:
						ASSERT (sa.cDims == 2);
						SAFEARRAYBOUND sab [2];

						sab [0] = sa.rgsabound [0];
						pStream->Read (&sab [1], sizeof (SAFEARRAYBOUND), NULL);

						// Compute array size:
						cdwElements = sa.rgsabound [0].cElements * sab [1].cElements;

						// Allocate array (specify basic, i.e. non-array, data type):
						vtVal.parray = SafeArrayCreate (vtVal.vt & ~VT_ARRAY, sa.cDims, sab);
						}

					// 1-D array
					else
						{
						// Compute array size:
						cdwElements = sa.rgsabound [0].cElements;

						// Allocate array (specify basic, i.e. non-array, data type):
						vtVal.parray = SafeArrayCreate (vtVal.vt & ~VT_ARRAY, sa.cDims, sa.rgsabound);
						}

					// Read array data:
					pStream->Read (vtVal.parray->pvData, sa.cbElements * cdwElements, NULL);
					}
					break;

				case VT_BSTR | VT_BYREF:
					ASSERT (FALSE);
					break;
				}

			// The client handle in the item header structure gives us a
			// pointer to the destination CKItem:
			CKItem *pItem = (CKItem *) itemheader.hClient;

			// Wrap use of pItem in exception handler in case pointer is bad:
			try
				{
				// Fill the item's data and quality:
				pItem->UpdateData (vtVal, itemheader.wQuality);
				}
			catch (...)
				{
				TRACE (_T("OTC: Server returned bad item data in advise stream (no timestamp)\r\n"));
				}

			// Clear variant for reuse:
			VariantClear (&vtVal);
			}
		}

	//////////////////////////////////////////////////	
	// DATA CHANGE WITH TIMESTAMP NOTIFICATION		//
	//////////////////////////////////////////////////
	else if (pFormatEtc->cfFormat == CF_DATA_CHANGE_TIME)
		{
		OPCGROUPHEADER groupheader;
		OPCITEMHEADER1 itemheader;
		VARIANT vtVal;

		// Read the group header:
		hr = pStream->Read (&groupheader,				// where to put the stream data
							sizeof (OPCGROUPHEADER),	// how much to read
							NULL);						// don't care about how many bytes are read

		// Release stream and return if read failed:
		if (FAILED (hr))
			{
			TRACE (_T("OTC: CKAdviseSink - IStream::Read GROUPHEADER failed.\r\n"));
			pStream->Release ();
			return;
			}

		// Post a "read complete" message if this is a read/refresh transaction
		// complete but not for unsolicited data change events.  Data change 
		// events will have a zero transaction ID.
		if (groupheader.dwTransactionID != 0)
			{
			// The client group handle in the group header structure gives us
			// a pointer to the destination CKGroup:
			CKGroup *pGroup = (CKGroup *) groupheader.hClientGroup;

			// Wrap use of pGroup in exception handler in case pointer is bad:
			try 
				{
				// Log transaction complete status:
				LogMsg (IDS_ASYNC10_READXACT_COMPLETE, groupheader.dwTransactionID, groupheader.dwItemCount,
					pGroup->GetName (), groupheader.hrStatus);
				}
			catch (...)
				{
				ASSERT (FALSE);
				}
			}

		// Initialize a variant to place a data value in:
		VariantInit (&vtVal);

		// Loop over items in the stream:
		for (DWORD dwItem = 0; dwItem < groupheader.dwItemCount; dwItem++)
			{
			// Compute offset of next item:
			dlibMove.HighPart = 0;
			dlibMove.LowPart = sizeof (OPCGROUPHEADER) + (dwItem * sizeof (OPCITEMHEADER1));

			// Seek to next item:
			hr = pStream->Seek (dlibMove, STREAM_SEEK_SET, NULL);

			// If seek failed, try to get next item:
			if (FAILED (hr))
				{
				TRACE (_T("OTC: CKAdviseSink - IStream::Seek Next Item failed.\r\n"));
				continue;
				}

			// Read the item header:
			hr = pStream->Read (&itemheader, sizeof (OPCITEMHEADER1), NULL);

			// If read failed, try to get next item:
			if (FAILED (hr))
				{
				TRACE (_T("OTC: CKAdviseSink - IStream::Read Item Header failed.\r\n"));
				continue;
				}

			// Seek to beginning of data:
			dlibMove.LowPart = itemheader.dwValueOffset;	
			hr = pStream->Seek (dlibMove, STREAM_SEEK_SET, NULL);

			// If seek failed, try to get next item:
			if (FAILED (hr))
				{
				TRACE (_T("OTC: CKAdviseSink - IStream::Seek Data failed.\r\n"));
				continue;
				}

			// Read the variant data:
			hr = pStream->Read (&vtVal, sizeof (VARIANT), NULL);

			// If read failed, try to get next item:
			if (FAILED (hr))
				{
				TRACE (_T("OTC: CKAdviseSink - IStream::Read Variant failed.\r\n"));
				continue;
				}

			// A little more work for strings and arrays:
			switch (vtVal.vt)
				{
				case VT_BSTR:
					{
					DWORD dwLength = 0;

					// Read string length:
					hr = pStream->Read (&dwLength, sizeof (DWORD), NULL); 
        
					// If read failed, try to get next item:
					if (FAILED (hr))
						{
						TRACE (_T("OTC: CKAdviseSink - IStream::Read string size failed.\r\n"));
						continue;
						}

					if (dwLength == 0)
						vtVal.bstrVal = NULL;
					else 
						{
						// Allocate memory for string.  We will free this once we copy
						// the contents of the string into the item object:
						vtVal.bstrVal = SysAllocStringLen (NULL, dwLength);

						if (vtVal.bstrVal != NULL)
							{
							// Read string data:
							hr = pStream->Read (vtVal.bstrVal, (dwLength + 1) * sizeof (OLECHAR), NULL);

							// If read failed, try to get next item:
							if (FAILED (hr))
								{
								TRACE (_T("OTC: CKAdviseSink - IStream::Read string value failed.\r\n"));
								SysFreeString (vtVal.bstrVal);
								continue;
								}
							}
						}
					}
					break;

				case VT_UI1	| VT_ARRAY:
				case VT_I1	| VT_ARRAY:
				case VT_UI2	| VT_ARRAY:
				case VT_I2	| VT_ARRAY:
				case VT_UI4	| VT_ARRAY:
				case VT_I4	| VT_ARRAY:
				case VT_R4	| VT_ARRAY:
				case VT_R8	| VT_ARRAY:
					{
					// Read array parameters:
					SAFEARRAY sa;
					DWORD cdwElements;
					pStream->Read (&sa, sizeof (SAFEARRAY), NULL);

					// 2-D array:
					if (sa.cDims != 1)
						{
						// Read array parameters for second dimension:
						ASSERT (sa.cDims == 2);
						SAFEARRAYBOUND sab [2];

						sab [0] = sa.rgsabound [0];
						pStream->Read (&sab [1], sizeof (SAFEARRAYBOUND), NULL);

						// Compute array size:
						cdwElements = sa.rgsabound [0].cElements * sab [1].cElements;

						// Allocate array (specify basic, i.e. non-array, data type):
						vtVal.parray = SafeArrayCreate (vtVal.vt & ~VT_ARRAY, sa.cDims, sab);
						}

					// 1-D array
					else
						{
						// Compute array size:
						cdwElements = sa.rgsabound [0].cElements;

						// Allocate array (specify basic, i.e. non-array, data type):
						vtVal.parray = SafeArrayCreate (vtVal.vt & ~VT_ARRAY, sa.cDims, sa.rgsabound);
						}

					// Read array data:
					pStream->Read (vtVal.parray->pvData, sa.cbElements * cdwElements, NULL);
					}
					break;

				case VT_BSTR | VT_BYREF:
					ASSERT (FALSE);
					break;
				}

			// The client handle in the item header structure gives us a
			// pointer to the destination CKItem:
			CKItem *pItem = (CKItem *) itemheader.hClient;

			// Wrap use of pItem in exception handler in case pointer is bad:
			try
				{
				// Fill the item's data, quality and timestamp:
				pItem->UpdateData (vtVal, itemheader.wQuality, itemheader.ftTimeStampItem);
				}
			catch (...)
				{
				TRACE (_T("OTC: Server returned bad item data in advise stream (with timestamp)\r\n"));
				}

			// Clear variant for reuse:
			VariantClear (&vtVal);
			}
		}

	//////////////////////////////////////////////////	
	// WRITE COMPLETE NOTIFICATION					//
	//////////////////////////////////////////////////
	else if (pFormatEtc->cfFormat == CF_WRITE_COMPLETE)
		{
		OPCGROUPHEADERWRITE groupheader;
		OPCITEMHEADERWRITE itemheader;

		// Read the group header:
		hr = pStream->Read (&groupheader,					// where to put the stream data
							sizeof (OPCGROUPHEADERWRITE),	// how much to read
							NULL);							// don't care about how many bytes are read

		// Release stream and return if read failed:
		if (FAILED (hr))
			{
			TRACE (_T("OTC: CKAdviseSink - IStream::Read GROUPHEADERWRITE failed.\r\n"));
			pStream->Release ();
			return;
			}
		
		// See which group this write transaction complete is for.  The 
		// client group handle in the group header structure gives us a
		// pointer to the destination CKGroup:
		CKGroup *pGroup = (CKGroup *) groupheader.hClientGroup;

		// Don't do anything with pGroup if it is an invalid pointer (i.e. == NULL):
		if (pGroup != NULL)
			{
			// Log "write complete" with status message:
			LogMsg (IDS_ASYNC10_WRITE_COMPLETE, groupheader.dwTransactionID, groupheader.dwItemCount,
				pGroup->GetName (), groupheader.hrStatus);

			// Loop over items:
			for (DWORD dwItem = 0; dwItem < groupheader.dwItemCount; dwItem++)
				{
				// Compute offset of next item:
				dlibMove.HighPart = 0;
				dlibMove.LowPart = sizeof (OPCGROUPHEADER) + (dwItem * sizeof (OPCITEMHEADERWRITE));

				// Seek to next item:
				hr = pStream->Seek (dlibMove, STREAM_SEEK_SET, NULL);

				// If seek failed, try to get next item:
				if (FAILED (hr))
					{
					TRACE (_T("OTC: CKAdviseSink - IStream::Seek Next Item failed.\r\n"));
					continue;
					}

				// read the item header:
				hr = pStream->Read (&itemheader, sizeof (OPCITEMHEADERWRITE), NULL);

				// If read failed, try to get next item:
				if (FAILED (hr))
					{
					TRACE (_T("OTC: CKAdviseSink - IStream::Read Item Header failed.\r\n"));
					continue;
					}

				// Check to see if write failed:
				if (FAILED (itemheader.dwError))
					{
					// The client handle in the item header structure gives us a
					// pointer to the destination CKItem:
					CKItem *pItem = (CKItem *) itemheader.hClient;

					// Log "failed write" message.  Wrap use of pItem with exception
					// handler in case pointer is bad:
					try
						{
						LogMsg (IDS_ASYNC10_WRITE_COMPLETE_FAILURE, groupheader.dwTransactionID,
							pItem->GetItemID (), itemheader.dwError);
						}
					catch (...)
						{
						TRACE (_T("OTC: CKAdviseSink - WriteComplete - Bad item handle\r\n"));
						}
					}
				}
			}
		else
			{
			TRACE (_T("OTC: CKAdviseSink - WriteComplete - Bad group handle\r\n"));
			}
		}

	//////////////////////////////////////////////////////	
	// WE DON'T EXPECT ANY OTHER TYPE OF NOTIFICATION	//
	//////////////////////////////////////////////////////
	else
		{
		ASSERT (FALSE);
		}
		
	// Release our stream on exit:
	pStream->Release ();
	}

⌨️ 快捷键说明

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