Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / IO / Packaging / unsafeIndexingFilterStream.cs / 1305600 / unsafeIndexingFilterStream.cs
//------------------------------------------------------------------------------ // Microsoft Avalon // Copyright (c) Microsoft Corporation, 2005 // // File: UnsafeIndexingFilterStream.cs // // Description: The class UnsafeIndexingFilterStream uses an OLE IStream component // passed on a indexing filter's IPersistStream interface to implement // the System.IO.Stream functions necessary for filtering a document. // In other words, it basically implements a seekable read-only stream. // // For a more complete example of an IStream adapter, see Listing 20.2 // in Adam Nathan's ".Net and COM". // // History: 02/15/05 - johnlarc - initial implementation //----------------------------------------------------------------------------- using System; using System.IO; using System.Runtime.InteropServices; // For Marshal using System.Windows; // for ExceptionStringTable using MS.Win32; // For NativeMethods using MS.Internal.Interop; // for IStream using System.Security; // For SecurityCritical namespace MS.Internal.IO.Packaging { ////// The class UnsafeIndexingFilterStream uses an OLE IStream component /// passed on an indexing filter's IPersistStream interface to implement /// the System.IO.Stream functions necessary for filtering a document. /// In other words, it basically implements a seekable read-only stream. /// ////// /// This class is used only by the Container filter, since the Xaml filter is not accessible directly /// from unmanaged code and so can use System.IO.Stream natively. /// /// This class does not own the process of closing the underlying stream. However, /// This class does own a reference to a COM object that should be released as a part of the Dispose pattern, /// so that the underlying unmanaged code doesn't keep the stream open indefinitely (or until GC gets to it) /// /// The definition of IStream that is used is MS.Internal.Interop.IStream rather than the standard one /// so as to allow efficient marshaling of arrays with specified offsets in Read. /// ////// Critical: Marking this as Security Critical as this stream serves a very specific functionality /// required for indexing content using unmanaged Indexing Services. We do not want managed /// code to start using this Stream implementation. /// This code is meant to be accessed only from unmanaged code. Currently there is one /// unmanaged caller. /// This stream- 1. Calls into unmanaged code. /// 2. Implements a seekable read-only stream on an OLE IStream component. /// 3. Behaves more like an unmanaged IStream as opposed to managed Stream. /// 4. This class does not do any elevation of privilege. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal class UnsafeIndexingFilterStream : Stream { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- ////// Build a System.IO.Stream implementation around an IStream component. /// ////// The client code is entirely responsible for the lifespan of the stream, /// and there is no way it can tip us off for when to release it. Therefore, /// its reference count is not incremented. The risk of the client /// releasing the IStream component before we're done with it is no worse than /// that of the client passing a pointer to garbage in the first place, and we /// cannot protect against that either. After all, the client is unmanaged and /// has endless possibilities of trashing the machine if she wishes to. /// internal UnsafeIndexingFilterStream(IStream oleStream) { if (oleStream == null) throw new ArgumentNullException("oleStream"); _oleStream = oleStream; _disposed = false; } //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- ////// Return the bytes requested. /// /// Destination buffer. /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. /// How many bytes requested. ///How many bytes were written into buffer. public unsafe override int Read(byte[] buffer, int offset, int count) { ThrowIfStreamDisposed(); // Check arguments. PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); // Reading 0 bytes is a no-op. if (count == 0) return 0; // Prepare location of return value and call the COM object. int bytesRead; IntPtr pBytesRead = new IntPtr(&bytesRead); // Prepare to restore position in case the read fails. long positionBeforeReadAttempt = this.Position; try { // Pin the array wrt GC while using an address in it. fixed (byte *bufferPointer = &buffer[offset]) { _oleStream.Read(new IntPtr(bufferPointer), count, pBytesRead); } } catch (COMException comException) { this.Position = positionBeforeReadAttempt; throw new IOException("Read", comException); } catch (IOException ioException) { this.Position = positionBeforeReadAttempt; throw new IOException("Read", ioException); } return bytesRead; } ////// Seek -unmanaged streams do not allow seeking beyond the end of the stream /// and since we rely on the underlying stream to validate and return the seek /// results, unlike managed streams where seeking beyond the end of the stream /// is allowed we will get an exception. /// /// Offset in byte. /// Offset origin (start, current, or end). public unsafe override long Seek(long offset, SeekOrigin origin) { ThrowIfStreamDisposed(); long position = 0; // The address of 'position' can be used without pinning the object, because it // is a value and is therefore allocated on the stack rather than the heap. IntPtr positionAddress = new IntPtr(&position); // The enum values of SeekOrigin match the STREAM_SEEK_* values. This // convention is as good as carved in stone, so there's no need for a switch here. _oleStream.Seek(offset, (int)origin, positionAddress); return position; } ////// SetLength /// ///not supported ////// Not supported. No indexing filter should require it. /// public override void SetLength(long newLength) { ThrowIfStreamDisposed(); throw new NotSupportedException(SR.Get(SRID.StreamDoesNotSupportWrite)); } ////// Write /// ///not supported ////// Not supported. No indexing filter should require it. /// public override void Write(byte[] buf, int offset, int count) { ThrowIfStreamDisposed(); throw new NotSupportedException(SR.Get(SRID.StreamDoesNotSupportWrite)); } ////// Flush /// public override void Flush() { ThrowIfStreamDisposed(); //This stream is always readonly, and calling this method is a no-op //No IndexingFilter should require this method. } //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ ////// Is stream readable? /// ////// We always return true, because there's no way of checking whether the caller /// has closed the stream. /// public override bool CanRead { get { return !_disposed; } } ////// Is stream seekable? /// public override bool CanSeek { get { // This information is not available from the underlying stream. // So one assumption has to be made. True is the most common for indexable streams. return !_disposed; } } ////// Is stream writable? /// public override bool CanWrite { get { return false; } } ////// Logical byte position in this stream /// public override long Position { get { ThrowIfStreamDisposed(); return Seek(0, SeekOrigin.Current); } set { ThrowIfStreamDisposed(); if (value < 0) throw new ArgumentException(SR.Get(SRID.CannotSetNegativePosition)); Seek(value, SeekOrigin.Begin); } } ////// Length. /// public override long Length { get { ThrowIfStreamDisposed(); // Retrieve stream stats. STATFLAG_NONAME means don't return the stream name. System.Runtime.InteropServices.ComTypes.STATSTG statstg; _oleStream.Stat(out statstg, NativeMethods.STATFLAG_NONAME); return statstg.cbSize; } } //----------------------------------------------------- // // Protected methods. // //------------------------------------------------------ ////// protected override void Dispose(bool disposing) { try { if (disposing) { if (_oleStream != null) { MS.Win32.UnsafeNativeMethods.SafeReleaseComObject(_oleStream); } } } finally { // Calls to Dispose(bool) are expected to bubble up through the class hierarchy. _oleStream = null; _disposed = true; base.Dispose(disposing); } } //----------------------------------------------------- // // Private methods. // //----------------------------------------------------- private void ThrowIfStreamDisposed() { if (_disposed) throw new ObjectDisposedException(null, SR.Get(SRID.StreamObjectDisposed)); } //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ private IStream _oleStream; // Underlying COM component. private bool _disposed; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // Microsoft Avalon // Copyright (c) Microsoft Corporation, 2005 // // File: UnsafeIndexingFilterStream.cs // // Description: The class UnsafeIndexingFilterStream uses an OLE IStream component // passed on a indexing filter's IPersistStream interface to implement // the System.IO.Stream functions necessary for filtering a document. // In other words, it basically implements a seekable read-only stream. // // For a more complete example of an IStream adapter, see Listing 20.2 // in Adam Nathan's ".Net and COM". // // History: 02/15/05 - johnlarc - initial implementation //----------------------------------------------------------------------------- using System; using System.IO; using System.Runtime.InteropServices; // For Marshal using System.Windows; // for ExceptionStringTable using MS.Win32; // For NativeMethods using MS.Internal.Interop; // for IStream using System.Security; // For SecurityCritical namespace MS.Internal.IO.Packaging { ////// Although UnsafeIndexingFilterStream does not close the underlying stream, it is responsible for releasing /// the ComObject it holds, so that unmanaged code can properly close the stream. /// /// This method gets invoked as part of the base class's Dispose() or Close() implementation. /// ////// The class UnsafeIndexingFilterStream uses an OLE IStream component /// passed on an indexing filter's IPersistStream interface to implement /// the System.IO.Stream functions necessary for filtering a document. /// In other words, it basically implements a seekable read-only stream. /// ////// /// This class is used only by the Container filter, since the Xaml filter is not accessible directly /// from unmanaged code and so can use System.IO.Stream natively. /// /// This class does not own the process of closing the underlying stream. However, /// This class does own a reference to a COM object that should be released as a part of the Dispose pattern, /// so that the underlying unmanaged code doesn't keep the stream open indefinitely (or until GC gets to it) /// /// The definition of IStream that is used is MS.Internal.Interop.IStream rather than the standard one /// so as to allow efficient marshaling of arrays with specified offsets in Read. /// ////// Critical: Marking this as Security Critical as this stream serves a very specific functionality /// required for indexing content using unmanaged Indexing Services. We do not want managed /// code to start using this Stream implementation. /// This code is meant to be accessed only from unmanaged code. Currently there is one /// unmanaged caller. /// This stream- 1. Calls into unmanaged code. /// 2. Implements a seekable read-only stream on an OLE IStream component. /// 3. Behaves more like an unmanaged IStream as opposed to managed Stream. /// 4. This class does not do any elevation of privilege. /// [SecurityCritical(SecurityCriticalScope.Everything)] internal class UnsafeIndexingFilterStream : Stream { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- ////// Build a System.IO.Stream implementation around an IStream component. /// ////// The client code is entirely responsible for the lifespan of the stream, /// and there is no way it can tip us off for when to release it. Therefore, /// its reference count is not incremented. The risk of the client /// releasing the IStream component before we're done with it is no worse than /// that of the client passing a pointer to garbage in the first place, and we /// cannot protect against that either. After all, the client is unmanaged and /// has endless possibilities of trashing the machine if she wishes to. /// internal UnsafeIndexingFilterStream(IStream oleStream) { if (oleStream == null) throw new ArgumentNullException("oleStream"); _oleStream = oleStream; _disposed = false; } //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- ////// Return the bytes requested. /// /// Destination buffer. /// The zero-based byte offset in buffer at which to begin storing the data read from the current stream. /// How many bytes requested. ///How many bytes were written into buffer. public unsafe override int Read(byte[] buffer, int offset, int count) { ThrowIfStreamDisposed(); // Check arguments. PackagingUtilities.VerifyStreamReadArgs(this, buffer, offset, count); // Reading 0 bytes is a no-op. if (count == 0) return 0; // Prepare location of return value and call the COM object. int bytesRead; IntPtr pBytesRead = new IntPtr(&bytesRead); // Prepare to restore position in case the read fails. long positionBeforeReadAttempt = this.Position; try { // Pin the array wrt GC while using an address in it. fixed (byte *bufferPointer = &buffer[offset]) { _oleStream.Read(new IntPtr(bufferPointer), count, pBytesRead); } } catch (COMException comException) { this.Position = positionBeforeReadAttempt; throw new IOException("Read", comException); } catch (IOException ioException) { this.Position = positionBeforeReadAttempt; throw new IOException("Read", ioException); } return bytesRead; } ////// Seek -unmanaged streams do not allow seeking beyond the end of the stream /// and since we rely on the underlying stream to validate and return the seek /// results, unlike managed streams where seeking beyond the end of the stream /// is allowed we will get an exception. /// /// Offset in byte. /// Offset origin (start, current, or end). public unsafe override long Seek(long offset, SeekOrigin origin) { ThrowIfStreamDisposed(); long position = 0; // The address of 'position' can be used without pinning the object, because it // is a value and is therefore allocated on the stack rather than the heap. IntPtr positionAddress = new IntPtr(&position); // The enum values of SeekOrigin match the STREAM_SEEK_* values. This // convention is as good as carved in stone, so there's no need for a switch here. _oleStream.Seek(offset, (int)origin, positionAddress); return position; } ////// SetLength /// ///not supported ////// Not supported. No indexing filter should require it. /// public override void SetLength(long newLength) { ThrowIfStreamDisposed(); throw new NotSupportedException(SR.Get(SRID.StreamDoesNotSupportWrite)); } ////// Write /// ///not supported ////// Not supported. No indexing filter should require it. /// public override void Write(byte[] buf, int offset, int count) { ThrowIfStreamDisposed(); throw new NotSupportedException(SR.Get(SRID.StreamDoesNotSupportWrite)); } ////// Flush /// public override void Flush() { ThrowIfStreamDisposed(); //This stream is always readonly, and calling this method is a no-op //No IndexingFilter should require this method. } //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ ////// Is stream readable? /// ////// We always return true, because there's no way of checking whether the caller /// has closed the stream. /// public override bool CanRead { get { return !_disposed; } } ////// Is stream seekable? /// public override bool CanSeek { get { // This information is not available from the underlying stream. // So one assumption has to be made. True is the most common for indexable streams. return !_disposed; } } ////// Is stream writable? /// public override bool CanWrite { get { return false; } } ////// Logical byte position in this stream /// public override long Position { get { ThrowIfStreamDisposed(); return Seek(0, SeekOrigin.Current); } set { ThrowIfStreamDisposed(); if (value < 0) throw new ArgumentException(SR.Get(SRID.CannotSetNegativePosition)); Seek(value, SeekOrigin.Begin); } } ////// Length. /// public override long Length { get { ThrowIfStreamDisposed(); // Retrieve stream stats. STATFLAG_NONAME means don't return the stream name. System.Runtime.InteropServices.ComTypes.STATSTG statstg; _oleStream.Stat(out statstg, NativeMethods.STATFLAG_NONAME); return statstg.cbSize; } } //----------------------------------------------------- // // Protected methods. // //------------------------------------------------------ ////// protected override void Dispose(bool disposing) { try { if (disposing) { if (_oleStream != null) { MS.Win32.UnsafeNativeMethods.SafeReleaseComObject(_oleStream); } } } finally { // Calls to Dispose(bool) are expected to bubble up through the class hierarchy. _oleStream = null; _disposed = true; base.Dispose(disposing); } } //----------------------------------------------------- // // Private methods. // //----------------------------------------------------- private void ThrowIfStreamDisposed() { if (_disposed) throw new ObjectDisposedException(null, SR.Get(SRID.StreamObjectDisposed)); } //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ private IStream _oleStream; // Underlying COM component. private bool _disposed; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved./// Although UnsafeIndexingFilterStream does not close the underlying stream, it is responsible for releasing /// the ComObject it holds, so that unmanaged code can properly close the stream. /// /// This method gets invoked as part of the base class's Dispose() or Close() implementation. /// ///
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SelectedDatesCollection.cs
- XmlSchemaSimpleContentRestriction.cs
- ClientSponsor.cs
- RowVisual.cs
- TimeIntervalCollection.cs
- GradientBrush.cs
- TabletCollection.cs
- MatrixAnimationUsingKeyFrames.cs
- XmlElementList.cs
- ImageSource.cs
- CookieHandler.cs
- WebGetAttribute.cs
- ZipIOZip64EndOfCentralDirectoryBlock.cs
- CounterSampleCalculator.cs
- Clipboard.cs
- XmlUrlResolver.cs
- VectorCollectionConverter.cs
- MenuScrollingVisibilityConverter.cs
- SearchExpression.cs
- JavaScriptSerializer.cs
- serverconfig.cs
- FreezableCollection.cs
- RecognizeCompletedEventArgs.cs
- SRef.cs
- FontConverter.cs
- OdbcConnectionPoolProviderInfo.cs
- WindowsAltTab.cs
- ExpandSegmentCollection.cs
- SHA384.cs
- ControlBuilder.cs
- RequestCache.cs
- HtmlUtf8RawTextWriter.cs
- XamlFigureLengthSerializer.cs
- DrawingGroup.cs
- TextOptionsInternal.cs
- Simplifier.cs
- WebAdminConfigurationHelper.cs
- FontStyles.cs
- EncryptedData.cs
- DbDataRecord.cs
- AudioStateChangedEventArgs.cs
- WebServiceClientProxyGenerator.cs
- HttpPostedFileBase.cs
- parserscommon.cs
- MemberPathMap.cs
- AutoResetEvent.cs
- InvalidDocumentContentsException.cs
- MailHeaderInfo.cs
- WebPartCatalogAddVerb.cs
- VisualStyleElement.cs
- UIElement3D.cs
- Tile.cs
- ExceptionUtil.cs
- StrokeNodeOperations2.cs
- SerialPinChanges.cs
- RouteParameter.cs
- Renderer.cs
- ObjectViewFactory.cs
- CounterSample.cs
- ApplicationSecurityInfo.cs
- SelectedGridItemChangedEvent.cs
- BindingExpression.cs
- SmtpCommands.cs
- MultitargetUtil.cs
- DbConvert.cs
- DatePicker.cs
- GridItemProviderWrapper.cs
- TimersDescriptionAttribute.cs
- RootDesignerSerializerAttribute.cs
- UnmanagedMemoryStreamWrapper.cs
- FigureParaClient.cs
- EntityTypeBase.cs
- Model3D.cs
- ParseNumbers.cs
- Label.cs
- GridViewHeaderRowPresenter.cs
- SoapCodeExporter.cs
- RegexCharClass.cs
- AttributeEmitter.cs
- CustomLineCap.cs
- _SafeNetHandles.cs
- TypeResolver.cs
- ResourceProviderFactory.cs
- DynamicEndpointElement.cs
- PrinterSettings.cs
- WebPartsPersonalizationAuthorization.cs
- GB18030Encoding.cs
- WebUtil.cs
- Button.cs
- BinHexEncoding.cs
- MetafileHeader.cs
- StateDesigner.Helpers.cs
- DetailsViewAutoFormat.cs
- ColumnClickEvent.cs
- MultiAsyncResult.cs
- ToolStripItemEventArgs.cs
- TextRunTypographyProperties.cs
- XmlArrayItemAttribute.cs
- DES.cs
- XmlQuerySequence.cs