Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

161 lines
4.6 KiB

/*--------------------------------------------------------------------------*
*
* Microsoft Windows
* Copyright (C) Microsoft Corporation, 1999 - 1999
*
* File: serial.cpp
*
* Contents: Object serialization class implementation
*
* History: 11-Feb-99 vivekj Created
*
*--------------------------------------------------------------------------*/
#include "stgio.h"
#include "stddbg.h"
#include "macros.h"
#include <comdef.h>
#include "serial.h"
/*+-------------------------------------------------------------------------*
*
* CSerialObject::Write
*
* PURPOSE: Writes an object with version and size information. This information
* is used when the object is read. If an unknown version of the object
* is presented, the data is discarded. This way, all known data can
* still be retrieved. (Useful for backward as well as forward compatibility.)
*
* PARAMETERS:
* IStream & stm :
*
* RETURNS:
* HRESULT
*
*+-------------------------------------------------------------------------*/
HRESULT
CSerialObjectRW::Write(IStream &stm)
{
HRESULT hr = S_OK;
UINT nVersion = GetVersion();
ULARGE_INTEGER nSeekPosMarker;
ULARGE_INTEGER nSeekPosNextObj;
LARGE_INTEGER lZero;
LARGE_INTEGER lint;
try
{
do // not a loop
{
lZero.LowPart = 0;
lZero.HighPart= 0;
lZero.QuadPart= 0; // just to be safe.
stm << nVersion; // save the version information
hr = stm.Seek(lZero, STREAM_SEEK_CUR, &nSeekPosMarker); // get the current location of the pointer
BREAK_ON_FAIL(hr);
::ZeroMemory(&nSeekPosNextObj, sizeof(nSeekPosNextObj) );
// should we use the low part only? Or will this cause a Y2K like crisis?
stm << nSeekPosNextObj.QuadPart; // not the correct value; need to come back and fix (done below)
#ifdef DBG
ULARGE_INTEGER nSeekPosMarker2;
hr = stm.Seek(lZero, STREAM_SEEK_CUR, &nSeekPosMarker2); // get the current location of the pointer
BREAK_ON_FAIL(hr);
#endif
hr = WriteSerialObject(stm); // write the internal data
BREAK_ON_FAIL(hr);
hr = stm.Seek(lZero, STREAM_SEEK_CUR, &nSeekPosNextObj);
BREAK_ON_FAIL(hr);
// go back to the placeholder marker
lint.QuadPart = nSeekPosMarker.QuadPart;
hr = stm.Seek(lint, STREAM_SEEK_SET, NULL);
BREAK_ON_FAIL(hr);
stm << nSeekPosNextObj.QuadPart; // the correct value of the marker
#ifdef DBG
ULARGE_INTEGER nSeekPosMarker3;
hr = stm.Seek(lZero, STREAM_SEEK_CUR, &nSeekPosMarker3); // get the current location of the pointer
BREAK_ON_FAIL(hr);
// make sure we're back in the same place
ASSERT( (nSeekPosMarker2.QuadPart == nSeekPosMarker3.QuadPart) );
#endif
lint.QuadPart = nSeekPosNextObj.QuadPart;
hr = stm.Seek(lint, STREAM_SEEK_SET, NULL);
BREAK_ON_FAIL(hr);
} while (false);
}
catch (_com_error& err)
{
hr = err.Error();
ASSERT (false && "Caught _com_error");
}
return hr;
}
/*+-------------------------------------------------------------------------*
*
* CSerialObject::Read
*
* PURPOSE:
*
* PARAMETERS:
* IStream & stm :
*
* RETURNS:
* HRESULT - S_OK if able to read the object.
* S_FALSE if skipped reading the object.
* E_FAIL Could not skip the object or something catastrophic.
*
*+-------------------------------------------------------------------------*/
HRESULT
CSerialObject::Read(IStream &stm)
{
HRESULT hr = S_OK;
UINT nVersion = 0;
ULARGE_INTEGER nSeekPosMarker;
ULARGE_INTEGER nSeekPosNextObj;
LARGE_INTEGER lint;
try
{
stm >> nVersion; // get the version number
stm >> nSeekPosNextObj.QuadPart; // get the offset to the next object
hr = ReadSerialObject(stm, nVersion);
if (hr==S_FALSE) // data skipped?
{
// an unknown version. Throw the data for that object away and continue to read other objects
lint.QuadPart = nSeekPosNextObj.QuadPart;
hr = stm.Seek(lint, STREAM_SEEK_SET, NULL);
if (SUCCEEDED (hr))
hr = S_FALSE; // propagate "data skipped"
}
}
catch (_com_error& err)
{
hr = err.Error();
ASSERT (false && "Caught _com_error");
}
return (hr);
}