Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Base / MS / Internal / IO / Packaging / CompoundFile / VersionedStreamOwner.cs / 1 / VersionedStreamOwner.cs
//------------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
// Description:
// This class provides file versioning support for streams provided by
// IDataTransform implementations and any client code that needs
// to store a FormatVersion at the beginning of a stream.
//
// History:
// 02/21/2006: BruceMac: Initial implementation.
//
//-----------------------------------------------------------------------------
using System;
using System.IO; // for Stream
using System.Windows; // ExceptionStringTable
using System.Globalization; // for CultureInfo
using System.Diagnostics; // for Debug.Assert
namespace MS.Internal.IO.Packaging.CompoundFile
{
///
/// Specialized stream that owns the FormatVersion
///
/// Dispose() functionality is handled by our subclass VersionedStream
internal class VersionedStreamOwner : VersionedStream
{
#region Stream Methods
///
/// Return the bytes requested from the container
///
public override int Read(byte[] buffer, int offset, int count)
{
// throw if version missing
ReadAttempt(true);
return BaseStream.Read(buffer, offset, count);
}
///
/// Write
///
public override void Write(byte[] buffer, int offset, int count)
{
WriteAttempt();
BaseStream.Write(buffer, offset, count);
}
///
/// ReadByte
///
public override int ReadByte()
{
ReadAttempt(true);
return BaseStream.ReadByte();
}
///
/// WriteByte
///
public override void WriteByte(byte b)
{
WriteAttempt();
BaseStream.WriteByte(b);
}
///
/// Seek
///
/// offset
/// origin
/// zero
public override long Seek(long offset, SeekOrigin origin)
{
ReadAttempt();
long temp = -1;
switch (origin)
{
// seek beyond the FormatVersion
case SeekOrigin.Begin:
temp = offset;
break;
case SeekOrigin.Current:
checked { temp = Position + offset; }
break;
case SeekOrigin.End:
checked { temp = Length + offset; }
break;
}
if (temp < 0)
throw new ArgumentException(SR.Get(SRID.SeekNegative));
checked { BaseStream.Position = temp + _dataOffset; }
return temp;
}
///
/// SetLength
///
public override void SetLength(long newLength)
{
if (newLength < 0)
throw new ArgumentOutOfRangeException("newLength");
WriteAttempt();
checked { BaseStream.SetLength(newLength + _dataOffset); }
}
///
/// Flush
///
public override void Flush()
{
CheckDisposed();
BaseStream.Flush();
}
#endregion Stream Methods
//-----------------------------------------------------
//
// Public Properties
//
//-----------------------------------------------------
#region Stream Properties
///
/// Current logical position within the stream
///
public override long Position
{
get
{
ReadAttempt(); // ensure _dataOffset is valid
return checked(BaseStream.Position - _dataOffset);
}
set
{
// share Seek logic and validation
Seek(value, SeekOrigin.Begin);
}
}
///
/// Length
///
public override long Length
{
get
{
ReadAttempt(); // ensure _dataOffset is valid
long temp = checked(BaseStream.Length - _dataOffset);
Invariant.Assert(temp >= 0); // catch any math errors
return temp;
}
}
///
/// Is stream readable?
///
/// returns false when called on disposed stream
public override bool CanRead
{
get
{
return (BaseStream != null) && BaseStream.CanRead && IsReadable;
}
}
///
/// Is stream seekable - should be handled by our owner
///
/// returns false when called on disposed stream
public override bool CanSeek
{
get
{
return (BaseStream != null) && BaseStream.CanSeek && IsReadable;
}
}
///
/// Is stream writeable?
///
/// returns false when called on disposed stream
public override bool CanWrite
{
get
{
return (BaseStream != null) && BaseStream.CanWrite && IsUpdatable;
}
}
#endregion
///
/// Constructor to use for the "versioned stream" - the one that actually houses the
/// persisted FormatVersion.
///
///
///
internal VersionedStreamOwner(Stream baseStream, FormatVersion codeVersion)
: base(baseStream)
{
_codeVersion = codeVersion;
}
internal bool IsUpdatable
{
get
{
CheckDisposed();
// first try to read the format version
EnsureParsed();
// We can write if either:
// 1. FileVersion doesn't exist - this is normal for a new, empty stream
// 2. It does exist and the FormatVersion indicates that we can update it
return (_fileVersion == null) ||
_fileVersion.IsUpdatableBy(_codeVersion.UpdaterVersion);
}
}
internal bool IsReadable
{
get
{
CheckDisposed();
// first try to read the format version
EnsureParsed();
// We can read if either:
// 1. FileVersion doesn't exist - normal for a new, empty stream
// 1. FileVersion exists and indicates that we can read it
return (_fileVersion == null) ||
_fileVersion.IsReadableBy(_codeVersion.ReaderVersion);
}
}
///
/// Callback for when a stream is written to
///
/// Can modify the FormatVersion stream pointer.
internal void WriteAttempt()
{
CheckDisposed(); // central location
if (!_writeOccurred)
{
// first try to read the format version
EnsureParsed();
if (_fileVersion == null)
{
// stream is empty so write our version
PersistVersion(_codeVersion);
}
else
{
// file version found - ensure we are able to update it
if (!_fileVersion.IsUpdatableBy(_codeVersion.UpdaterVersion))
{
throw new FileFormatException(
SR.Get(
SRID.UpdaterVersionError,
_fileVersion.UpdaterVersion,
_codeVersion
)
);
}
// if our version is different than previous
// updater then "update" the updater
if (_codeVersion.UpdaterVersion != _fileVersion.UpdaterVersion)
{
_fileVersion.UpdaterVersion = _codeVersion.UpdaterVersion;
PersistVersion(_fileVersion);
}
}
_writeOccurred = true;
}
}
internal void ReadAttempt()
{
ReadAttempt(false);
}
///
/// Callback for when a Stream is read from
///
/// Can modify the FormatVersion stream pointer.
/// caller requires an existing FormatVersion
internal void ReadAttempt(bool throwIfEmpty)
{
CheckDisposed(); // central location
// only do this once
if (!_readOccurred)
{
// read
EnsureParsed();
// first usage?
if (throwIfEmpty || BaseStream.Length > 0)
{
if (_fileVersion == null)
throw new FileFormatException(SR.Get(SRID.VersionStreamMissing));
// compare versions
// verify we can read this version
if (!_fileVersion.IsReadableBy(_codeVersion.ReaderVersion))
{
throw new FileFormatException(
SR.Get(
SRID.ReaderVersionError,
_fileVersion.ReaderVersion,
_codeVersion
)
);
}
}
_readOccurred = true;
}
}
//------------------------------------------------------
//
// Private Methods
//
//-----------------------------------------------------
///
/// Ensure that the version is persisted
///
/// Leaves stream at position just after the FormatVersion.
/// Destructive. This is called automatically from WriteAttempt but callers
/// can call directly if they have changed the stream contents to a format
/// that is no longer compatible with the persisted FormatVersion. If
/// this is not called directly, and a FormatVersion was found in the file
/// then only the Updater field is modified.
///
private void PersistVersion(FormatVersion version)
{
if (!BaseStream.CanWrite)
throw new NotSupportedException(SR.Get(SRID.WriteNotSupported));
// normalize and save
long tempPos = checked(BaseStream.Position - _dataOffset);
BaseStream.Seek(0, SeekOrigin.Begin);
// update _dataOffset
long offset = version.SaveToStream(BaseStream);
_fileVersion = version; // we know what it is - no need to deserialize
// existing value - ensure we didn't change sizes as this could lead to
// data corruption
if ((_dataOffset != 0) && (offset != _dataOffset))
throw new FileFormatException(SR.Get(SRID.VersionUpdateFailure));
// at this point we know the offset
_dataOffset = offset;
// restore and shift
checked { BaseStream.Position = tempPos + _dataOffset; }
}
///
/// Load and compare feature identifier
///
/// There is no need for this method to maintain any previous Seek pointer.
/// This method only modifies the stream position when called for the first time with a non-empty
/// stream. It is always called from Seek() and set_Position, which subsequently modify the stream
/// pointer as appropriate after the call.
private void EnsureParsed()
{
// empty stream cannot have a version in it
if ((_fileVersion == null) && (BaseStream.Length > 0))
{
Debug.Assert(_dataOffset == 0);
// if no version was found and we cannot read from it, then the format is invalid
if (!BaseStream.CanRead)
throw new NotSupportedException(SR.Get(SRID.ReadNotSupported));
//
// The physical stream begins with a header that identifies the transform to
// which the stream belongs. The "logical" stream object handed to us by the
// compound file begins -after- this stream header, so when we seek to the
// "beginning" of this stream, we are actually seeking to the location after
// the stream header, where the instance data starts.
//
BaseStream.Seek(0, SeekOrigin.Begin);
//
// The instance data starts with format version information for this transform.
//
_fileVersion = FormatVersion.LoadFromStream(BaseStream);
//
// Ensure that the feature name is as expected.
//
// NOTE: We preserve case, but do case-insensitive comparison.
if (String.CompareOrdinal(
_fileVersion.FeatureIdentifier.ToUpper(CultureInfo.InvariantCulture),
_codeVersion.FeatureIdentifier.ToUpper(CultureInfo.InvariantCulture)) != 0)
{
throw new FileFormatException(
SR.Get(
SRID.InvalidTransformFeatureName,
_fileVersion.FeatureIdentifier,
_codeVersion.FeatureIdentifier
)
);
}
_dataOffset = BaseStream.Position;
}
}
//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
private bool _writeOccurred; // did one of our streams get written to?
private bool _readOccurred; // did one of our streams get read from?
private FormatVersion _codeVersion; // code version
private FormatVersion _fileVersion; // current file version (null if not read or created yet)
private long _dataOffset = 0; // where FormatVersion ends and data begins
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
// Description:
// This class provides file versioning support for streams provided by
// IDataTransform implementations and any client code that needs
// to store a FormatVersion at the beginning of a stream.
//
// History:
// 02/21/2006: BruceMac: Initial implementation.
//
//-----------------------------------------------------------------------------
using System;
using System.IO; // for Stream
using System.Windows; // ExceptionStringTable
using System.Globalization; // for CultureInfo
using System.Diagnostics; // for Debug.Assert
namespace MS.Internal.IO.Packaging.CompoundFile
{
///
/// Specialized stream that owns the FormatVersion
///
/// Dispose() functionality is handled by our subclass VersionedStream
internal class VersionedStreamOwner : VersionedStream
{
#region Stream Methods
///
/// Return the bytes requested from the container
///
public override int Read(byte[] buffer, int offset, int count)
{
// throw if version missing
ReadAttempt(true);
return BaseStream.Read(buffer, offset, count);
}
///
/// Write
///
public override void Write(byte[] buffer, int offset, int count)
{
WriteAttempt();
BaseStream.Write(buffer, offset, count);
}
///
/// ReadByte
///
public override int ReadByte()
{
ReadAttempt(true);
return BaseStream.ReadByte();
}
///
/// WriteByte
///
public override void WriteByte(byte b)
{
WriteAttempt();
BaseStream.WriteByte(b);
}
///
/// Seek
///
/// offset
/// origin
/// zero
public override long Seek(long offset, SeekOrigin origin)
{
ReadAttempt();
long temp = -1;
switch (origin)
{
// seek beyond the FormatVersion
case SeekOrigin.Begin:
temp = offset;
break;
case SeekOrigin.Current:
checked { temp = Position + offset; }
break;
case SeekOrigin.End:
checked { temp = Length + offset; }
break;
}
if (temp < 0)
throw new ArgumentException(SR.Get(SRID.SeekNegative));
checked { BaseStream.Position = temp + _dataOffset; }
return temp;
}
///
/// SetLength
///
public override void SetLength(long newLength)
{
if (newLength < 0)
throw new ArgumentOutOfRangeException("newLength");
WriteAttempt();
checked { BaseStream.SetLength(newLength + _dataOffset); }
}
///
/// Flush
///
public override void Flush()
{
CheckDisposed();
BaseStream.Flush();
}
#endregion Stream Methods
//-----------------------------------------------------
//
// Public Properties
//
//-----------------------------------------------------
#region Stream Properties
///
/// Current logical position within the stream
///
public override long Position
{
get
{
ReadAttempt(); // ensure _dataOffset is valid
return checked(BaseStream.Position - _dataOffset);
}
set
{
// share Seek logic and validation
Seek(value, SeekOrigin.Begin);
}
}
///
/// Length
///
public override long Length
{
get
{
ReadAttempt(); // ensure _dataOffset is valid
long temp = checked(BaseStream.Length - _dataOffset);
Invariant.Assert(temp >= 0); // catch any math errors
return temp;
}
}
///
/// Is stream readable?
///
/// returns false when called on disposed stream
public override bool CanRead
{
get
{
return (BaseStream != null) && BaseStream.CanRead && IsReadable;
}
}
///
/// Is stream seekable - should be handled by our owner
///
/// returns false when called on disposed stream
public override bool CanSeek
{
get
{
return (BaseStream != null) && BaseStream.CanSeek && IsReadable;
}
}
///
/// Is stream writeable?
///
/// returns false when called on disposed stream
public override bool CanWrite
{
get
{
return (BaseStream != null) && BaseStream.CanWrite && IsUpdatable;
}
}
#endregion
///
/// Constructor to use for the "versioned stream" - the one that actually houses the
/// persisted FormatVersion.
///
///
///
internal VersionedStreamOwner(Stream baseStream, FormatVersion codeVersion)
: base(baseStream)
{
_codeVersion = codeVersion;
}
internal bool IsUpdatable
{
get
{
CheckDisposed();
// first try to read the format version
EnsureParsed();
// We can write if either:
// 1. FileVersion doesn't exist - this is normal for a new, empty stream
// 2. It does exist and the FormatVersion indicates that we can update it
return (_fileVersion == null) ||
_fileVersion.IsUpdatableBy(_codeVersion.UpdaterVersion);
}
}
internal bool IsReadable
{
get
{
CheckDisposed();
// first try to read the format version
EnsureParsed();
// We can read if either:
// 1. FileVersion doesn't exist - normal for a new, empty stream
// 1. FileVersion exists and indicates that we can read it
return (_fileVersion == null) ||
_fileVersion.IsReadableBy(_codeVersion.ReaderVersion);
}
}
///
/// Callback for when a stream is written to
///
/// Can modify the FormatVersion stream pointer.
internal void WriteAttempt()
{
CheckDisposed(); // central location
if (!_writeOccurred)
{
// first try to read the format version
EnsureParsed();
if (_fileVersion == null)
{
// stream is empty so write our version
PersistVersion(_codeVersion);
}
else
{
// file version found - ensure we are able to update it
if (!_fileVersion.IsUpdatableBy(_codeVersion.UpdaterVersion))
{
throw new FileFormatException(
SR.Get(
SRID.UpdaterVersionError,
_fileVersion.UpdaterVersion,
_codeVersion
)
);
}
// if our version is different than previous
// updater then "update" the updater
if (_codeVersion.UpdaterVersion != _fileVersion.UpdaterVersion)
{
_fileVersion.UpdaterVersion = _codeVersion.UpdaterVersion;
PersistVersion(_fileVersion);
}
}
_writeOccurred = true;
}
}
internal void ReadAttempt()
{
ReadAttempt(false);
}
///
/// Callback for when a Stream is read from
///
/// Can modify the FormatVersion stream pointer.
/// caller requires an existing FormatVersion
internal void ReadAttempt(bool throwIfEmpty)
{
CheckDisposed(); // central location
// only do this once
if (!_readOccurred)
{
// read
EnsureParsed();
// first usage?
if (throwIfEmpty || BaseStream.Length > 0)
{
if (_fileVersion == null)
throw new FileFormatException(SR.Get(SRID.VersionStreamMissing));
// compare versions
// verify we can read this version
if (!_fileVersion.IsReadableBy(_codeVersion.ReaderVersion))
{
throw new FileFormatException(
SR.Get(
SRID.ReaderVersionError,
_fileVersion.ReaderVersion,
_codeVersion
)
);
}
}
_readOccurred = true;
}
}
//------------------------------------------------------
//
// Private Methods
//
//-----------------------------------------------------
///
/// Ensure that the version is persisted
///
/// Leaves stream at position just after the FormatVersion.
/// Destructive. This is called automatically from WriteAttempt but callers
/// can call directly if they have changed the stream contents to a format
/// that is no longer compatible with the persisted FormatVersion. If
/// this is not called directly, and a FormatVersion was found in the file
/// then only the Updater field is modified.
///
private void PersistVersion(FormatVersion version)
{
if (!BaseStream.CanWrite)
throw new NotSupportedException(SR.Get(SRID.WriteNotSupported));
// normalize and save
long tempPos = checked(BaseStream.Position - _dataOffset);
BaseStream.Seek(0, SeekOrigin.Begin);
// update _dataOffset
long offset = version.SaveToStream(BaseStream);
_fileVersion = version; // we know what it is - no need to deserialize
// existing value - ensure we didn't change sizes as this could lead to
// data corruption
if ((_dataOffset != 0) && (offset != _dataOffset))
throw new FileFormatException(SR.Get(SRID.VersionUpdateFailure));
// at this point we know the offset
_dataOffset = offset;
// restore and shift
checked { BaseStream.Position = tempPos + _dataOffset; }
}
///
/// Load and compare feature identifier
///
/// There is no need for this method to maintain any previous Seek pointer.
/// This method only modifies the stream position when called for the first time with a non-empty
/// stream. It is always called from Seek() and set_Position, which subsequently modify the stream
/// pointer as appropriate after the call.
private void EnsureParsed()
{
// empty stream cannot have a version in it
if ((_fileVersion == null) && (BaseStream.Length > 0))
{
Debug.Assert(_dataOffset == 0);
// if no version was found and we cannot read from it, then the format is invalid
if (!BaseStream.CanRead)
throw new NotSupportedException(SR.Get(SRID.ReadNotSupported));
//
// The physical stream begins with a header that identifies the transform to
// which the stream belongs. The "logical" stream object handed to us by the
// compound file begins -after- this stream header, so when we seek to the
// "beginning" of this stream, we are actually seeking to the location after
// the stream header, where the instance data starts.
//
BaseStream.Seek(0, SeekOrigin.Begin);
//
// The instance data starts with format version information for this transform.
//
_fileVersion = FormatVersion.LoadFromStream(BaseStream);
//
// Ensure that the feature name is as expected.
//
// NOTE: We preserve case, but do case-insensitive comparison.
if (String.CompareOrdinal(
_fileVersion.FeatureIdentifier.ToUpper(CultureInfo.InvariantCulture),
_codeVersion.FeatureIdentifier.ToUpper(CultureInfo.InvariantCulture)) != 0)
{
throw new FileFormatException(
SR.Get(
SRID.InvalidTransformFeatureName,
_fileVersion.FeatureIdentifier,
_codeVersion.FeatureIdentifier
)
);
}
_dataOffset = BaseStream.Position;
}
}
//------------------------------------------------------
//
// Private Fields
//
//------------------------------------------------------
private bool _writeOccurred; // did one of our streams get written to?
private bool _readOccurred; // did one of our streams get read from?
private FormatVersion _codeVersion; // code version
private FormatVersion _fileVersion; // current file version (null if not read or created yet)
private long _dataOffset = 0; // where FormatVersion ends and data begins
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- _Events.cs
- BreakRecordTable.cs
- MethodCallConverter.cs
- XmlSchemaValidator.cs
- AsyncStreamReader.cs
- EditorAttribute.cs
- ChtmlLinkAdapter.cs
- COM2PictureConverter.cs
- SkewTransform.cs
- RightsManagementLicense.cs
- HttpModule.cs
- Native.cs
- UnsafeNativeMethods.cs
- OleDbReferenceCollection.cs
- MouseButtonEventArgs.cs
- ReferentialConstraintRoleElement.cs
- CurrencyWrapper.cs
- SafeTokenHandle.cs
- DesignTimeSiteMapProvider.cs
- FamilyTypeface.cs
- CatalogPartCollection.cs
- SoapSchemaMember.cs
- prompt.cs
- ExceptionDetail.cs
- ServerIdentity.cs
- CircleHotSpot.cs
- TrackBarRenderer.cs
- X509Extension.cs
- DesignerForm.cs
- BitmapMetadataEnumerator.cs
- OleDbDataAdapter.cs
- SqlAliasesReferenced.cs
- DockPanel.cs
- Quad.cs
- CallbackTimeoutsBehavior.cs
- RunClient.cs
- ConstrainedDataObject.cs
- SiteMapHierarchicalDataSourceView.cs
- HttpConfigurationSystem.cs
- SortDescription.cs
- ApplicationActivator.cs
- UserInitiatedNavigationPermission.cs
- XPathNavigatorReader.cs
- Stack.cs
- ParseNumbers.cs
- WindowsToolbarAsMenu.cs
- HttpListenerException.cs
- GeneralTransform3DGroup.cs
- RadioButtonList.cs
- PerfProviderCollection.cs
- DataGridViewHitTestInfo.cs
- TryExpression.cs
- DetailsViewCommandEventArgs.cs
- FrameworkName.cs
- BeginEvent.cs
- MemberPathMap.cs
- TemplateControlCodeDomTreeGenerator.cs
- UnescapedXmlDiagnosticData.cs
- StateElement.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- Transform.cs
- PointAnimationBase.cs
- MenuItemCollection.cs
- DiffuseMaterial.cs
- AuthenticationException.cs
- PenThreadPool.cs
- TextMarkerSource.cs
- Point3DConverter.cs
- TimeZoneInfo.cs
- WindowsStatusBar.cs
- ExpressionContext.cs
- DecoderExceptionFallback.cs
- ListViewGroupCollectionEditor.cs
- OrderedDictionary.cs
- EntityContainerAssociationSetEnd.cs
- SpecularMaterial.cs
- ListBox.cs
- DBCommandBuilder.cs
- DataGridPageChangedEventArgs.cs
- XmlObjectSerializerWriteContextComplex.cs
- ServiceControllerDesigner.cs
- DesignOnlyAttribute.cs
- SqlErrorCollection.cs
- WorkflowServiceAttributesTypeConverter.cs
- CmsUtils.cs
- UpdateTranslator.cs
- PolicyManager.cs
- EditingMode.cs
- DocumentGrid.cs
- BaseInfoTable.cs
- FormViewInsertEventArgs.cs
- ServiceReference.cs
- xmlsaver.cs
- SessionStateUtil.cs
- TypeToArgumentTypeConverter.cs
- RoutingExtension.cs
- RuntimeVariablesExpression.cs
- odbcmetadatacollectionnames.cs
- ObjectNotFoundException.cs
- DoubleLinkListEnumerator.cs