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
- ResourceSet.cs
- ActiveXSite.cs
- Control.cs
- DataGrid.cs
- TextLineResult.cs
- DynamicValidator.cs
- WebPartConnectionsCancelEventArgs.cs
- UnsupportedPolicyOptionsException.cs
- SamlAdvice.cs
- WinEventWrap.cs
- UserPreferenceChangingEventArgs.cs
- SchemaCollectionPreprocessor.cs
- OleDbStruct.cs
- Delegate.cs
- BinaryMethodMessage.cs
- XMLDiffLoader.cs
- NamespaceInfo.cs
- DecimalKeyFrameCollection.cs
- SQLResource.cs
- OpenFileDialog.cs
- NameValueSectionHandler.cs
- XMLDiffLoader.cs
- PropertyCollection.cs
- NativeCompoundFileAPIs.cs
- HttpHandlersSection.cs
- QilTernary.cs
- ToolStripItemDataObject.cs
- BooleanConverter.cs
- QilFunction.cs
- WebResponse.cs
- AttributeInfo.cs
- AbandonedMutexException.cs
- XamlDesignerSerializationManager.cs
- ParserExtension.cs
- BulletChrome.cs
- TextClipboardData.cs
- DnsPermission.cs
- LayoutSettings.cs
- ThreadStateException.cs
- IUnknownConstantAttribute.cs
- DbDeleteCommandTree.cs
- OracleInfoMessageEventArgs.cs
- ResourceDescriptionAttribute.cs
- HostVisual.cs
- CheckBoxField.cs
- FontFamilyConverter.cs
- CompoundFileDeflateTransform.cs
- TableLayoutPanelCodeDomSerializer.cs
- HashCryptoHandle.cs
- Int32AnimationUsingKeyFrames.cs
- TextServicesManager.cs
- HMACSHA384.cs
- PostBackTrigger.cs
- TextElementCollectionHelper.cs
- ExplicitDiscriminatorMap.cs
- ListBoxItemWrapperAutomationPeer.cs
- SchemaElement.cs
- BitmapMetadata.cs
- TargetPerspective.cs
- BoundField.cs
- Int64Animation.cs
- VoiceInfo.cs
- MimeMapping.cs
- SerialStream.cs
- CodeAttributeArgumentCollection.cs
- WindowCollection.cs
- CryptoKeySecurity.cs
- TagPrefixCollection.cs
- FloatUtil.cs
- PerCallInstanceContextProvider.cs
- SchemaInfo.cs
- TextStore.cs
- LessThan.cs
- CodePageUtils.cs
- TagPrefixInfo.cs
- WebPartManager.cs
- Monitor.cs
- CacheChildrenQuery.cs
- WpfWebRequestHelper.cs
- ControlValuePropertyAttribute.cs
- XmlKeywords.cs
- ComponentResourceKey.cs
- Model3D.cs
- ToolboxItemAttribute.cs
- XsltInput.cs
- UnsafeNativeMethodsTablet.cs
- HandleCollector.cs
- ListViewCommandEventArgs.cs
- SafeMemoryMappedFileHandle.cs
- ErrorHandler.cs
- SQLGuid.cs
- WebScriptEnablingElement.cs
- TabPanel.cs
- sitestring.cs
- DataColumnChangeEvent.cs
- SqlAliaser.cs
- ComponentDispatcherThread.cs
- DependencyObjectType.cs
- CompleteWizardStep.cs
- EntryWrittenEventArgs.cs