Code:
/ 4.0 / 4.0 / untmp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- MemoryStream.cs
- WebRequestModuleElement.cs
- StringFreezingAttribute.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- FixedNode.cs
- DocumentXPathNavigator.cs
- CircleHotSpot.cs
- CompositeCollection.cs
- PagesSection.cs
- DefaultAsyncDataDispatcher.cs
- TableRowCollection.cs
- ScrollItemProviderWrapper.cs
- XmlProcessingInstruction.cs
- HtmlInputCheckBox.cs
- ButtonChrome.cs
- SharedStatics.cs
- recordstate.cs
- Socket.cs
- EntityStoreSchemaGenerator.cs
- validationstate.cs
- MenuItemStyleCollection.cs
- login.cs
- TextTreeTextNode.cs
- HttpCachePolicyElement.cs
- TableLayoutPanelResizeGlyph.cs
- SAPICategories.cs
- Util.cs
- SchemaDeclBase.cs
- DataSourceGroupCollection.cs
- File.cs
- DynamicDataRouteHandler.cs
- SmtpSpecifiedPickupDirectoryElement.cs
- WindowPatternIdentifiers.cs
- StrokeCollectionDefaultValueFactory.cs
- TypeHelper.cs
- TransformerConfigurationWizardBase.cs
- CookieHandler.cs
- InheritanceContextChangedEventManager.cs
- XmlElement.cs
- LinqDataSourceSelectEventArgs.cs
- WorkflowRuntimeEndpoint.cs
- _NestedMultipleAsyncResult.cs
- ScriptDescriptor.cs
- PathFigure.cs
- PreparingEnlistment.cs
- ipaddressinformationcollection.cs
- _StreamFramer.cs
- ProfilePropertySettingsCollection.cs
- DeclarativeExpressionConditionDeclaration.cs
- EFDataModelProvider.cs
- BitmapEditor.cs
- SchemaImporterExtensionElementCollection.cs
- WebServiceTypeData.cs
- TimeEnumHelper.cs
- HyperLink.cs
- PropertyEntry.cs
- WindowsTab.cs
- CompressEmulationStream.cs
- GeometryCollection.cs
- SqlProfileProvider.cs
- RegularExpressionValidator.cs
- UnknownWrapper.cs
- RequestCachingSection.cs
- TextSelection.cs
- CallbackHandler.cs
- UserMapPath.cs
- GradientBrush.cs
- MenuBase.cs
- ContentPlaceHolderDesigner.cs
- QueueProcessor.cs
- sapiproxy.cs
- TemplateGroupCollection.cs
- ProtocolsSection.cs
- WorkflowInstance.cs
- CodeCompileUnit.cs
- CompleteWizardStep.cs
- SkipStoryboardToFill.cs
- SelectingProviderEventArgs.cs
- Cloud.cs
- PersonalizationDictionary.cs
- SessionStateUtil.cs
- InheritanceAttribute.cs
- unsafenativemethodsother.cs
- recordstatefactory.cs
- UrlPath.cs
- EdmSchemaError.cs
- VirtualPathProvider.cs
- TypeUsageBuilder.cs
- EtwTrace.cs
- HintTextMaxWidthConverter.cs
- XmlSchemaExternal.cs
- RequestNavigateEventArgs.cs
- ResourceReferenceKeyNotFoundException.cs
- _AcceptOverlappedAsyncResult.cs
- ConnectionStringsExpressionEditor.cs
- FamilyTypefaceCollection.cs
- ConversionContext.cs
- PathGradientBrush.cs
- FormViewDeleteEventArgs.cs
- HwndSubclass.cs