Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / 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
- ErrorWebPart.cs
- EventManager.cs
- AudioFormatConverter.cs
- shaper.cs
- HealthMonitoringSectionHelper.cs
- ThreadStateException.cs
- SynchronizedDispatch.cs
- TypeReference.cs
- TemplateControlBuildProvider.cs
- GenericAuthenticationEventArgs.cs
- RestHandler.cs
- CompiledQueryCacheEntry.cs
- SourceItem.cs
- TimeIntervalCollection.cs
- Boolean.cs
- AnimatedTypeHelpers.cs
- CodeSubDirectory.cs
- HtmlMeta.cs
- SessionStateContainer.cs
- BuilderPropertyEntry.cs
- UpDownBase.cs
- AssemblyNameProxy.cs
- MatrixStack.cs
- DBPropSet.cs
- PathTooLongException.cs
- XmlTextWriter.cs
- FixedBufferAttribute.cs
- NumberEdit.cs
- LoadWorkflowByInstanceKeyCommand.cs
- NavigatorOutput.cs
- FontCacheLogic.cs
- InstanceHandleConflictException.cs
- NavigatorOutput.cs
- TableDetailsCollection.cs
- Rfc2898DeriveBytes.cs
- SafePEFileHandle.cs
- ToolStripDropDownMenu.cs
- ListViewSelectEventArgs.cs
- AstTree.cs
- ObjectParameterCollection.cs
- Journaling.cs
- SessionState.cs
- NavigationWindowAutomationPeer.cs
- CompletionBookmark.cs
- SqlParameter.cs
- StaticExtension.cs
- compensatingcollection.cs
- WmlLiteralTextAdapter.cs
- ToggleButton.cs
- TextTreeFixupNode.cs
- DragEvent.cs
- ControlBuilderAttribute.cs
- DrawListViewItemEventArgs.cs
- TransformCollection.cs
- ComboBox.cs
- VectorKeyFrameCollection.cs
- _AuthenticationState.cs
- LayoutDump.cs
- DiagnosticTrace.cs
- ExternalFile.cs
- StatusStrip.cs
- MessageDecoder.cs
- FileVersion.cs
- ResolvedKeyFrameEntry.cs
- KeyEventArgs.cs
- MimeTextImporter.cs
- ConfigurationPermission.cs
- Environment.cs
- _NativeSSPI.cs
- FixedSOMFixedBlock.cs
- ViewStateModeByIdAttribute.cs
- LayoutManager.cs
- RSACryptoServiceProvider.cs
- NavigatingCancelEventArgs.cs
- ListViewDeleteEventArgs.cs
- ResXBuildProvider.cs
- BitmapEffectRenderDataResource.cs
- StateWorkerRequest.cs
- PersonalizableTypeEntry.cs
- VideoDrawing.cs
- GridEntryCollection.cs
- TaskHelper.cs
- Storyboard.cs
- QueryOperationResponseOfT.cs
- CompositeCollectionView.cs
- TextBox.cs
- AddInProcess.cs
- DesignConnection.cs
- RegexCompiler.cs
- StringCollectionEditor.cs
- dbdatarecord.cs
- WindowsTooltip.cs
- DropShadowBitmapEffect.cs
- LocalizabilityAttribute.cs
- UrlAuthorizationModule.cs
- ContextActivityUtils.cs
- BindingWorker.cs
- RequestCacheManager.cs
- XmlDownloadManager.cs
- RelationHandler.cs