Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / MS / Internal / IO / Packaging / unsafeIndexingFilterStream.cs / 1 / 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.
//
//------------------------------------------------------
///
///
/// 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.
///
///
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
{
///
/// 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.
//
//------------------------------------------------------
///
///
/// 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.
///
///
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.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SerializationException.cs
- LinqDataSourceInsertEventArgs.cs
- XamlStyleSerializer.cs
- Memoizer.cs
- ScriptingProfileServiceSection.cs
- HealthMonitoringSectionHelper.cs
- ImageDrawing.cs
- Formatter.cs
- ColorConvertedBitmap.cs
- ContentType.cs
- WeakHashtable.cs
- ContextMarshalException.cs
- HintTextMaxWidthConverter.cs
- SerializerProvider.cs
- CryptoApi.cs
- LabelDesigner.cs
- XmlDataSourceView.cs
- ConfigurationUtility.cs
- _NegoState.cs
- RefreshPropertiesAttribute.cs
- MultidimensionalArrayItemReference.cs
- SafeNativeMethodsOther.cs
- TableRowGroup.cs
- CompilerGlobalScopeAttribute.cs
- TypeSystem.cs
- _UncName.cs
- WindowsListBox.cs
- MouseButtonEventArgs.cs
- AccessDataSourceView.cs
- TokenBasedSet.cs
- RecordConverter.cs
- AxWrapperGen.cs
- DataGridViewLinkCell.cs
- ExpandCollapseIsCheckedConverter.cs
- Currency.cs
- BamlTreeMap.cs
- MdImport.cs
- SerializationInfo.cs
- ParentQuery.cs
- DataGridViewRowConverter.cs
- X509ChainPolicy.cs
- SerializerWriterEventHandlers.cs
- DataErrorValidationRule.cs
- DataBindingExpressionBuilder.cs
- SingleAnimation.cs
- LZCodec.cs
- ObjectStateFormatter.cs
- SmtpFailedRecipientException.cs
- CollectionBuilder.cs
- GPPOINT.cs
- TextTreeNode.cs
- QilNode.cs
- BrushMappingModeValidation.cs
- CompositeScriptReferenceEventArgs.cs
- ButtonBase.cs
- ComplexPropertyEntry.cs
- DataGridViewAccessibleObject.cs
- OrderedDictionaryStateHelper.cs
- DetailsViewPageEventArgs.cs
- MemberAccessException.cs
- ProcessRequestArgs.cs
- Latin1Encoding.cs
- XmlSigningNodeWriter.cs
- RenderDataDrawingContext.cs
- BitmapInitialize.cs
- ListViewHitTestInfo.cs
- Base64Encoder.cs
- Vector3DCollection.cs
- Int32RectConverter.cs
- ValidationHelpers.cs
- TableParagraph.cs
- ApplicationActivator.cs
- Scene3D.cs
- cookiecontainer.cs
- WeakRefEnumerator.cs
- BoundPropertyEntry.cs
- ConfigXmlSignificantWhitespace.cs
- IdentityHolder.cs
- XmlSchemaObjectTable.cs
- AsyncSerializedWorker.cs
- COM2FontConverter.cs
- PathData.cs
- QilGeneratorEnv.cs
- SimpleTypeResolver.cs
- ListViewInsertEventArgs.cs
- RequestBringIntoViewEventArgs.cs
- ConnectorDragDropGlyph.cs
- Point3D.cs
- FileDialogCustomPlaces.cs
- HostedTcpTransportManager.cs
- CodePropertyReferenceExpression.cs
- PrintController.cs
- SdlChannelSink.cs
- SqlLiftWhereClauses.cs
- ActiveXHelper.cs
- MouseBinding.cs
- HttpRequest.cs
- ASCIIEncoding.cs
- Dynamic.cs
- RequestDescription.cs