Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Packaging / CompoundFile / VersionedStreamOwner.cs / 1305600 / 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 using MS.Internal.WindowsBase; 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 using MS.Internal.WindowsBase; 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
- CompoundFileStorageReference.cs
- TypeAccessException.cs
- BitArray.cs
- ExpressionWriter.cs
- ChildTable.cs
- IntermediatePolicyValidator.cs
- Range.cs
- TableColumnCollectionInternal.cs
- ShaderRenderModeValidation.cs
- objectquery_tresulttype.cs
- BaseParser.cs
- ViewKeyConstraint.cs
- ScriptResourceHandler.cs
- TypeBinaryExpression.cs
- TextTreeInsertElementUndoUnit.cs
- TableStyle.cs
- IItemProperties.cs
- DataGrid.cs
- mda.cs
- SafeArrayRankMismatchException.cs
- Encoding.cs
- QuotaThrottle.cs
- NativeRecognizer.cs
- CompiledIdentityConstraint.cs
- MessageDesigner.cs
- MiniLockedBorderGlyph.cs
- ISO2022Encoding.cs
- SerialPinChanges.cs
- CompiledQuery.cs
- SamlAssertion.cs
- AsmxEndpointPickerExtension.cs
- Stopwatch.cs
- DataGridHelper.cs
- ConfigurationProviderException.cs
- Config.cs
- RoleManagerModule.cs
- Fonts.cs
- SQLChars.cs
- FocusTracker.cs
- NoPersistScope.cs
- DataKeyCollection.cs
- VerticalAlignConverter.cs
- SecurityPermission.cs
- CompilerState.cs
- BehaviorEditorPart.cs
- GridViewDeleteEventArgs.cs
- SchemaMerger.cs
- GreenMethods.cs
- DesignerSerializationVisibilityAttribute.cs
- SoapMessage.cs
- PrintPreviewDialog.cs
- ConsoleCancelEventArgs.cs
- HtmlCommandAdapter.cs
- ImageResources.Designer.cs
- GACIdentityPermission.cs
- TextUtf8RawTextWriter.cs
- UIElement.cs
- DataSet.cs
- Int64AnimationBase.cs
- InvokeMethod.cs
- CustomValidator.cs
- WebException.cs
- CompiledIdentityConstraint.cs
- SqlMethodCallConverter.cs
- TraceContextRecord.cs
- ParserOptions.cs
- TaskForm.cs
- NativeMethods.cs
- EdmPropertyAttribute.cs
- EntityDataSourceDataSelection.cs
- IIS7UserPrincipal.cs
- XmlStringTable.cs
- StaticSiteMapProvider.cs
- GroupStyle.cs
- PathData.cs
- Pen.cs
- OperatorExpressions.cs
- MetaData.cs
- Processor.cs
- _NtlmClient.cs
- SparseMemoryStream.cs
- ExpressionPrinter.cs
- StylusPointProperties.cs
- ImageCodecInfoPrivate.cs
- followingquery.cs
- HttpCookieCollection.cs
- RuntimeConfigLKG.cs
- PeerOutputChannel.cs
- CoreSwitches.cs
- infer.cs
- StorageModelBuildProvider.cs
- ListViewSortEventArgs.cs
- COM2Properties.cs
- DataGridViewTextBoxCell.cs
- AssemblyBuilder.cs
- WSSecurityTokenSerializer.cs
- OdbcTransaction.cs
- Validator.cs
- PointAnimationUsingKeyFrames.cs
- safex509handles.cs