📄 advisesink.cpp
字号:
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 + -